I wish to be able to change the table a class is mapped to at run time, I can’t do this if all the mappings are defined with attributes. Therefore is there a way to define the mappings at runtime in code.
(I would rather not have to maintain xml mapping files.)
Say I have two tables:
- OldData
- NewData
and sometimes I wished to query OldData and other times I wished to query NewData. I want to use the same code to build the queries in both cases.
See also “How to map an Entity framework model to a table name dynamically“
In order to make this truly transparent, you have to jump through some pretty crazy hoops, but it can be done by overriding all the
Meta***classes with your own derived types.This would actually be fairly straightforward with a proxy/method interception library like Castle, but assuming the lowest common denominator here, it’s basically a long and boring ordeal of implementing every single meta method to wrap the original type, because you can’t derive directly from any of the attribute mapping classes.
I’ll try to stick to the important overrides here; if you don’t see a particular method/property in the code below, it means that the implementation is literally a one-liner that wraps the “inner” method/property and returns the result. I’ve posted the whole thing, one-line methods and all, on PasteBin so you can cut/paste for testing/experimentation.
The first thing you need is a quick override declaration, which looks like this:
Now the meta classes. Starting from the lowest level, you have to implement a
MetaTypewrapper:Again, you have to implement about 30 properties/methods for this, I’ve excluded the ones that just
return innerType.XYZ. Still with me? OK, next is theMetaTable:Yup, boring. OK, next is the
MetaModelitself. Here things get a little more interesting, this is where we really start declaring overrides:We’re almost done! Now you just need the mapping source:
Now we can FINALLY start using this (phew):
I’ve tested this with queries and also with insertions (
InsertOnSubmit). It’s possible, actually rather likely, that I’ve missed something in my very basic testing. Oh, and this will only work if the two tables are literally exactly the same, column names and all.It will probably mess up if this table has any associations (foreign keys), since you’d have to override the association names too, on both ends. I’ll leave that as an exercise to the reader, since thinking about it makes my head hurt. You’d probably be better off just removing any associations from this particular table, so you don’t have to deal with that headache.
Have fun!