2

I'm working on a composite total system application which different companies may add different modules but there is only one database.I have a Generic repository in my framework which is technology independent (I mean it's provider base and for now the defult provider is EF 4.1 ).I have seprated common layer which contains poco entities and there is also different entities per module in their own assemblies. Now the problem is the entities mapping.I don't have any access to my entities from my EF provider project as I don't know the future modules ! so how can I map my entities in a generic approach? Is it possible?

One solution that I think is having a config file and adding entities FullName then ieterating and reflecting each one and then I can add them in OnModelCreat(...) method but ofcourse there is some performance concerns.

Edit: Firstly thanks for your reply Ladislav. But there is some more info for you.

You can make a requirement that each module must contain mapping classes for every new entity it uses. When you start the application you will just use reflection to get all classes derived from StructuralTypeConfiguration<> (includes both entities and complex types), create instances of these types and add them to Configurations collection in DbModelBuilder (can be done in OnModelCreating).

It will take some time but it will happens only once when context is used for the first time. You can trigger this creation during application start - applications simply need some time to start and configure all infrastructure they need to use.

Edit:

I have to reference EntityFramework.dll in every module which is not suitable in this case.

Yes. You want to allow other developers to define their own entities which will be persisted by your core application. In such case they must use your persistence framework of choice to tell your application how to persist their entities.

==> as I mentioned before, EF is not my only DataProvider ! I have to have some other DP such as a dataprovider for DB4O and etc so I don't want to reference each provider's dependencies to each module ... therefore I need to encapsulate EF in a separate assembly

If you use repositories each module should even contain its own repositories for working with its own entities - generic repository doesn't exists. Generic repository is redundant useless layer which only makes work with ORM of your choice much harder. To make it clear - correct implementation of repository pattern is not generic. It is specific and it expose data access functionality for single entity or aggregate root.

==> may I ask for any reliable ref ?! Why should I add one repository per module in case only one repository can do all of my requirements? which is redundant ? In my oppenion using specific or generic rep are both correct in a correct situation.90% of my modules has same requirements from a repository and all of them should have CRUD ...

If you don't want EF dependency in modules either don't use EF at all or define your own intermediate mapping layer which will be converted to specific mapping in your application - a lot of work with zero added value.

==> In fact I'm trying to define my own mapping layer because I need it in my app architecture.it is not useless for me.This was the only reason that I asked how to implement it.I'm looking for the best solution and I hope you could help me to hand on it :)

Other option is simply not allowing your modules to use new entities because it looks more like your current expectation. If module developer must define new database tables for his entities he must also be able to work with persistence and define mapping between tables and his entities.

==> Good Idea but not suitable for my case ;)

I have to reflect each module dll at startup which means lots of heavy dll's to be reflected and ... is there any other Idea?

Have you ever seen applications like Photoshop, Visual Studio or even MS Office applications during their startup? What do you think is happening when you see splash screen? Application is initializing - it is loading and initializing its features and plugins. Even server application can need minutes to be fully started. You are building modular application (not composite) so you must pay for that requirement.

==> Yeah I think I saw some of them ! If they are loading for example all the pallets or sidebars at startup they have to employ me .Hey dear microsoft if you don't know what is the defer loading I can help you to improve your performance :)

If you don't want to use reflection yourselves you can use MEF for building modularized infrastructure.

==>I'm already using Prism and MEF for handling modularity but only for modules not for my providers...

It sounds that EF is not a good solution for enterprise composite app right?

You didn't propose any enterprise requirement that shouldn't be fulfilled by EF. You just fights with your expectations to allow module developers to use new entities but don't give them ability to describe how these entities will be persisted - but who will describe it?

==> A model or a intermediate mapper layer which will work in each module load and map the entities if the EF support (which can't as I know) I need something like bootstrapper for each provider to map the entities :)

You are not building composite application. Composite application takes existing functionality (components, existing applications) which works separately and composite them to a new application. You are building modular application where your core can host another modules but those modules cannot run without your hosting infrastructure.

==>I'm not going to give lecture about my app and its architecture but I think just this much is enough that you know this is a composite/modular application ...

Should I switch to Model First?!!

Model first (and EDMX generally) is really not suitable for your expectations because in case of model first each module will need its own EDMX file and its own context.

==> but I can change the model and the xml of EDMX file at runtime right?!

You also mustn't use automatic database generation by code first because any new module will either break your application or EF will delete your current database.

==> thanks for this advice although I knew it before but ofcourse I will give more attention to it.

Reza_pvb
  • 31
  • 2
  • Don't copy whole my answer - especially if you don't use quotation. It makes your question unreadable. – Ladislav Mrnka Feb 05 '12 at 21:41
  • is it better now ?! But my problem is still there and instead of learning how to map entities for each module separately I learned how to use stackoverflow's quotation marks ! – Reza_pvb Feb 06 '12 at 07:27
  • It is little bit unfair. I got the way how EF support this but you didn't like it. The problem is that you are not asking question for EF. You are asking question how to make a custom mapping definition. That should be trivial - just define mapping in whatever way you want, expose `GetAllMappings` on your core module interface and during startup call this method for all mappings. Each module developer will have to implement this method and return you mappings for all new entities and your core will have to convert it to provider specific mapping. – Ladislav Mrnka Feb 06 '12 at 09:21

1 Answers1

2

You can make a requirement that each module must contain mapping classes for every new entity it uses. When you start the application you will just use reflection to get all classes derived from StructuralTypeConfiguration<> (includes both entities and complex types), create instances of these types and add them to Configurations collection in DbModelBuilder (can be done in OnModelCreating).

It will take some time but it will happens only once when context is used for the first time. You can trigger this creation during application start - applications simply need some time to start and configure all infrastructure they need to use.

Edit:

I have to reference EntityFramework.dll in every module which is not suitable in this case.

Yes. You want to allow other developers to define their own entities which will be persisted by your core application. In such case they must use your persistence framework of choice to tell your application how to persist their entities.

If you use repositories each module should even contain its own repositories for working with its own entities - generic repository doesn't exists. Generic repository is redundant useless layer which only makes work with ORM of your choice much harder. To make it clear - correct implementation of repository pattern is not generic. It is specific and it expose data access functionality for single entity or aggregate root.

If you don't want EF dependency in modules either don't use EF at all or define your own intermediate mapping layer which will be converted to specific mapping in your application - a lot of work with zero added value.

Other option is simply not allowing your modules to use new entities because it looks more like your current expectation. If module developer must define new database tables for his entities he must also be able to work with persistence and define mapping between tables and his entities.

I have to reflect each module dll at startup which means lots of heavy dll's to be reflected and ... is there any other Idea?

Have you ever seen applications like Photoshop, Visual Studio or even MS Office applications during their startup? What do you think is happening when you see splash screen? Application is initializing - it is loading and initializing its features and plugins. Even server application can need minutes to be fully started. You are building modular application (not composite) so you must pay for that requirement.

If you don't want to use reflection yourselves you can use MEF for building modularized infrastructure.

It sounds that EF is not a good solution for enterprise composite app right?

You didn't propose any enterprise requirement that shouldn't be fulfilled by EF. You just fight with your expectations to allow module developers to use new entities but don't give them ability to describe how these entities will be persisted - but who will describe it?

You are not building composite application. Composite application takes existing functionality (components, existing applications) which works separately and composethem to a new application. You are building modular application where your core can host another modules but those modules cannot run without your hosting infrastructure.

Should I switch to Model First?!!

Model first (and EDMX generally) is really not suitable for your expectations because in case of model first each module will need its own EDMX file and its own context.

You also mustn't use automatic database generation by code first because any new module will either break your application or EF will delete your current database.

Last Edit because this is not discussion forum:

EF is not my only DataProvider! I have to have some other DP such as ...

I don't know why you do that but it is wrong. Single application (even modular) should use single provider (ORM mapper). If you have other data providers because of some legacy code so be it but you should establish single provider policy for all new code. Otherwise you are fighting with your over architectured application not with EF. In such case your modules will always use only single dependency on provider.

May I ask for any reliable ref?! Why should I add one repository per module in case only one repository can do all of my requirements? which is redundant?

Ref is experience. There are hundreds of questions about repository and EF. If you want to use full advantage of EF, generic repository will not allow it or it will have to expose features which are not available in implementations for other providers. If you use repository just to expose CRUD for single entity you are just wrapping what IDbSet already provides. I understand that you are using repositories to hide your providers hell.

In fact I'm trying to define my own mapping layer because I need it in my app architecture.it is not useless for me.

You are going to write some custom mapping (probably XML) and convertor for each provider specific mapping. I'm not sure what better answer do you expect - except that it is not a good way to go.

A model or a intermediate mapper layer which will work in each module load and map the entities if the EF support (which can't as I know) I need something like bootstrapper for each provider to map the entities

It is not missing part of EF. It is simply out of scope of EF. Any intermediate layer defined by EF will still be part of EF and not supported by other tools. EF can load entities when it creates model but to load them you must tell EF about their existence and how to map them - that was what my initial answer explained.

I'm not going to give lecture about my app and it's architecture but I think just this much is enough that you know this is a composite/modular application

It can be, but composite part don't have these challenges because each component of composite application is independent on the rest and can use completely different persistence. The challenge you are facing is internal to every single modular component.

But I can change the model and the xml of EDMX file at runtime right?

Try it. Hint: there is no public API to operate with this XML on low level basis and there is no public API to modify loaded model. It is possible to change EDMX before you load it but it generally means writing custom parser and xml builder for SSDL, MSL and CSDL. You will have one set of mapping files updated by all installed modules. You will also have to code reverse operation to uninstall the module and correctly remove all features from mapping. Any bug can broke whole your application because mapping will be corrupted. My initial idea with loaded configurations for code mapping will take you less than one day. How long will it take to build this?

If you want to go this way remove EF from your project completely and start using NHibernate and hbm mapping files. Module developer will create assembly with module logic and new entities, script for database tables and hbm file for each entity. Module installation will create table, add assembly to module location and add hbm files to mapping pick up directory. Your NHibernate session will load all mapping files from that directory.

Ladislav Mrnka
  • 349,807
  • 56
  • 643
  • 654
  • This solution means that 1.I have to reference EntityFramework.dll in every module which is not suitable in this case. 2. I have to reflect each module dll at startup which means lots of heavy dll's to be reflected and ... is there any other Idea? it sounds that EF is not a good solution for enterprise composite app right?! should I switch to Model First?!! – Reza_pvb Feb 05 '12 at 13:22