NeddySpaghetti
NeddySpaghetti

Reputation: 13495

Modifying an ORM model at run time

there has been quite bit of discussion on this topic ( Modifying an Entity Framework Model at Run-Time), but so far I haven't been able to find a nice solution to the problem. We currently have a model built with EF 4.0 and need to allow customers to add custom fields to various tables. We have currently solved the problem with a few generic tables that describe the new properties, but we're finding that the solution is not performing well.

Does anyone know of a good way to dynamically add columns to the database and also update the ORM to reflect that at run-time?

Upvotes: 1

Views: 1067

Answers (1)

Ladislav Mrnka
Ladislav Mrnka

Reputation: 364369

There is no good, nice or manageable way to update EF at runtime to reflect changes in the database. If you really have a database which must change at runtime EF is not good tool for you. EF is strongly typed - every change to database must be reflected not only in mapping but also in entity classes used for loading and persisting data.

Changing entity classes at runtime always goes to area of emitting IL code at runtime. If you pass the process of creating dynamic assembly with dynamic module and dynamic entity types you will face a lot of new challenges:

  • You will not change your existing types - you will generate a new type every time the user adds or removes some property.
  • A new type generation brings a new performance cost for rebuilding context's metadata workspace. You must also make sure that this is correctly synchronized if you use it on a server. Another problem is that all existing instances of the old type (before adding or removing property) are now unknown to new instances of EF context and cannot be persisted. If you want to persist them as well you need EF context instances with old metadata workspace as well.
  • A lot of your code will probably use dynamic instead of real type = no compile time checking. Inheritance and interfaces will not be useful when interacting directly with EF because inheritance must be mapped (you don't want it) and interfaces are not accepted by EF.
  • The new type is unknown at design time - you cannot use it for design time code and compilation.
  • EF doesn't like dynamic or ExpandoObject because it uses reflection for mapping -> at runtime your dynamic instance must be correct type otherwise reflection will not work.
  • How to write queries for dynamic type? The query always starts at generic instance of DbSet or ObjectSet created for concrete type - you must be able to make those instances dynamically as well. Generic argument must be a type mapped to current context - dynamic will not help in this case because it is not a mapped type.
  • .NET has a nice behavior for this case. It cannot unload assembly. So every time you generate a new type you will have an old time loaded as well.

Do you still want to change EF at runtime? Your current approach is correct one. Simply tune it for better performance but beware that these requirements always come with performance costs - especially with EF.

Alternatively use the last approach mentioned with linked table - fixed number of predefined custom fields directly in the main entity.

Upvotes: 2

Related Questions