Acesso de dados para aplicativos compostos

5

Gostaria de saber se alguém pode compartilhar seus pensamentos, experiências e orientações sobre como abordar a camada de acesso a dados para um aplicativo composível?

Por aplicativo composable, quero dizer um aplicativo com a camada de domínio composta de módulos. O objetivo é tornar o aplicativo altamente extensível ao 'conectar' módulos adicionais (ou de substituição). Cada módulo encapsula (e isola) um conjunto de funcionalidades relacionadas.

Meu dilema é a abordagem correta para a camada de acesso a dados para suportar essa capacidade de composição (modularidade) e, ao mesmo tempo, fornecer isolamento do banco de dados de back-end. Como cada "módulo" pode implementar seu próprio conjunto de objetos de domínio, realmente não vejo um ORM como o EF funcionando, a menos que eu simplesmente crie um contexto de mega dados ou faça alterações na camada de acesso a dados toda vez que um novo módulo for introduzido (o que não é possível se o módulo for adicionado por terceiros ou como uma extensão pós-implantação).

Por que vale a pena, este é um aplicativo de escala empresarial com um banco de dados contendo mais de 200 tabelas e uma tonelada de sproc, udfs, etc.

Que conselho você pode compartilhar?

UPDATE

Confirmei hoje que usaremos um armazenamento de dados legado para a solução que utiliza procedimentos armazenados e funções definidas pelo usuário para a maioria das operações de acesso a dados. Nossa esperança é evoluir para longe com o passar do tempo, mas o orçamento e o cronograma do projeto ditam a construção dos bancos de dados existentes.

Isso muda seus pensamentos?

    
por SonOfPirate 30.07.2011 / 03:46
fonte

4 respostas

1

Não há uma regra rígida e rápida que um aplicativo precise usar um único DbContext; Eu separaria as coisas em um contexto de dados principais e outro DbContext mais focado. Ou coisas que nem sequer são DbContexts quando os dados não estão vindo de um banco de dados relacional. . .

    
por 01.08.2011 / 22:38
fonte
4

Da minha experiência (porque fiz um CMS usando o .NET Framework e o LINQ para o SQL ORM):

Qualquer CMS deve abordar três grupos, ou seja, desenvolvedores , designers e usuários . Quando você diz módulo, é como se você falasse sobre o grupo de desenvolvedores . Agora você tem que considerar estes itens:

  1. Forneça uma infraestrutura e peça aos usuários que usem sua infraestrutura ao desenvolver seus módulos (por exemplo, o WordPress é assim e tem uma classe chamada wp_options e, sempre que você quiser armazenar ou recuperar uma opção, é recomendável usar essa classe). Desta forma, seu único trabalho poderia ser criar algumas classes básicas como DataAccessBase ou algumas classes genéricas, etc.
  2. Qualquer CMS é feito de core + partes extensíveis . Em alguns aplicativos do CMS, a taxonomia não é extensível, portanto, faz parte do núcleo. Em muitos aplicativos CMS, a segurança não é extensível, portanto, faz parte do núcleo. Faça o que fizer, você deve implementar um núcleo. Nesse caso, você pode solicitar que os desenvolvedores usem seu núcleo para partes não extensíveis, como segurança, associação, taxonomia, comentários, opções etc. Por exemplo, você pode ter uma classe chamada UserFacade com um método chamado IsAuthenticated . Em seguida, os desenvolvedores podem usar sua abstração para obter o que desejam do núcleo.
  3. Cada CMS tem uma implementação diferente do banco de dados. Alguns usam o modelo EAV e permitem criar Tipos de Conteúdo dinamicamente, enquanto outros simplesmente solicitam que você crie suas tabelas relacionadas. Se o seu CMS for da segunda categoria, o desenvolvedor do módulo só poderá usar sua infraestrutura para se conectar ao banco de dados, mas outras partes da recuperação e armazenamento de dados serão específicas do módulo e cada desenvolvedor deverá ter sua própria implementação. No entanto, se o seu CMS for da primeira categoria, você poderá simplesmente fornecer uma camada de abstração para que os desenvolvedores de módulos nunca atinjam seu banco de dados (por exemplo, eles podem escrever uma linha de código como: dynamic riddles = EntityProvider.GetList("Riddle"); ou EntityPersister.Save(riddleKeyValueDictionary);
por 30.07.2011 / 09:35
fonte
2

Eu fiz isso e é realmente muito simples com um ORM como (N-) Hibernate.

Se um contexto EF é semelhante a uma sessão no Hibernate, então um mega contexto claramente é algo que você deve evitar! No entanto, o Hibernate tem um Session-Factory, que lê todos os mapeamentos e cria as sessões (provavelmente contextos no EF) quando você precisa delas. E esta fábrica pode ser a mega fábrica sem ser um antipadrão.

Cada módulo pode conter seus próprios mapeamentos e entidades. Hibernate faz um ótimo trabalho de persistência ignorância! O ponto chave aqui é que o contexto é alimentado com os mapeamentos durante o tempo de inicialização e não no tempo de design.

Acabei de criar um SessionManager (que contém o NHibernates SessionFactory). Durante a inicialização, todos os mapeamentos de todos os módulos são registrados. Temos cerca de 200 tabelas e quase tantas entidades e isso não é um problema, também não há problemas de memória. O gerenciador de sessões cria sessões de banco de dados conforme necessário. Normalmente, temos aqui uma sessão por abordagem de caso de uso (traduz uma sessão por diálogo para nós muito bem).

Como todos os módulos compartilham o mesmo host, eles têm acesso a um contêiner IoC, para que possam resolver a fábrica da sessão e obter quantas sessões quiserem.

Os únicos problemas representam os mapeamentos de herança intermodular de tempos em tempos. Os mapeamentos de herança intermodular podem ser bastante complicados e algumas entidades não podem ser mapeadas por herança como gostaríamos que fossem. Mas estes casos eram raros (talvez uma, duas entidades desses 200) e depois nós fizemos principalmente relações HasOne, etc.

    
por 30.07.2011 / 09:17
fonte
1

Algumas ideias:

Crie uma camada de mapeamento, que mapeia objetos de domínio de nível de módulo para os objetos que o DAL consome. A camada de mapeamento representaria a transformação em dados de módulos de domínio para dados consumíveis do DAL. Internamente, o módulo de domínio poderia usar suas próprias estruturas de dados, mas quando chegasse a hora de falar com o DAL, essas estruturas de dados teriam que ser mapeadas para objetos consumíveis do DAL.

Módulo - > Objetos de domínio - > Mapeador - > Objetos Dal - > DAL

Se esses módulos realmente estenderem o banco de dados, algum tipo de esquema de banco de dados extensível seria necessário e os módulos chamariam os métodos genéricos de esquema extensível para salvar os dados.

Além disso, você poderia explorar os internos para se comunicar com o DAL com uma interface que pode expor ExecuteReader, ExecuteSclare, ExecuteNonQuery, etc. Isso significa que o módulo de domínio pode falar diretamente com o DAL, mas eu acho que é muita exposição direta .

    
por 30.07.2011 / 06:28
fonte