1) O que você faz se quiser trocar os ORMs, teria código ORM específico em seu aplicativo se não o contivesse em um repositório.
Eu ainda não estava em uma posição em que a empresa de repente decidiu mudar a tecnologia de acesso a dados. Se isso acontecer, será necessário algum trabalho. Costumo abstrair operações de acesso a dados por meio de interfaces. O repositório é uma maneira de resolver isso.
Eu teria um assembly diferente para implementação concreta da minha camada de acesso a dados. Por exemplo, eu posso ter:
Company.Product.Data
e Company.Product.Data.EntityFramework
montagens. O primeiro assembly seria usado apenas para interfaces, enquanto outro seria uma implementação concreta da lógica de acesso a dados do Entity Framework.
2) O padrão do repositório ainda é válido quando você não está usando um ORM e você está usando o ADO.net para acessar dados e preencher os dados de objetos?
Eu acho que cabe a você decidir qual padrão é válido ou não. Eu usei um padrão de repositório na camada de apresentação. Uma coisa a ter em mente é que as pessoas gostam de lançar responsabilidades nos repositórios. Antes que você perceba, sua classe de repositório estará dançando, cantando e fazendo todo tipo de coisa. Você quer evitar isso.
Eu vi uma classe de repositório que começou com as responsabilidades GetAll, GetById, Update e Delete, o que é bom. Quando o projeto foi concluído, essa mesma classe tinha dezenas de métodos (responsabilidades) que nunca deveriam estar lá. Por exemplo, GetByForename, GetBySurname, UpdateWithExclusions e todos os tipos de coisas malucas.
É aqui que consultas e comandos entram em jogo.
3) Se você usa um ORM, mas não o padrão do repositório, onde mantém as consultas mais usadas. Seria sensato representar cada consulta como uma classe e ter algum tipo de fábrica de consultas para criar instâncias?
Eu acho que é uma boa idéia usar consultas e comandos em vez de repositórios. Eu faço o seguinte:
Defina a interface para uma consulta. Isso o ajudará a testar a unidade. Por exemplopublic interface IGetProductsByCategoryQuery { ... }
Defina a implementação concreta de uma consulta. Você poderá injetá-las através da estrutura de IoC de sua escolha. Por exemplopublic class GetProductsByCategoryQuery : IGetProductsByCategoryQuery
Agora, em vez de poluir o repositório com dezenas de responsabilidades, simplesmente agrupo minhas consultas em espaços para nome. Por exemplo, uma interface para a consulta acima pode residir: Company.SolutionName.Products.Queries
e a implementação pode residir emCompany.SolutionName.Products.Queries.Implementation
Quando se trata de atualizar ou remover dados, eu uso o padrão de comando da mesma maneira.
Alguns podem discordar e dizer que antes que o projeto seja concluído, você terá dezenas de classes e espaços para nome. Sim você irá. Na minha opinião, é uma coisa boa, pois você pode navegar pela solução no IDE de sua escolha e ver instantaneamente que tipo de responsabilidades um componente possui. Se você decidiu usar um padrão de repositório, precisará procurar dentro de cada classe de repositório tentando definir suas responsabilidades.