Linq to Entities control table name resolution at runtime

782 views Asked by At

I've implemented a content management system that deals with a certain kind of object, and now the client has introduced another kind of object, whose structure and behavior is exactly the same, but separate. They want to be able to switch modes, where each mode behaves identically, except that one deals with one object type and the other with the other.

Suppose the first object type is stored in a table called TBL_OBJECT, and the second in one called TBL_OBJECT_NEW. I'm looking for a way to use my existing code, but to be able to switch on the fly and have it switch to the other table. Because the structure is identical, this is conceptually possible. The only problem is that in L2E, the table name is saved as attribute and compiled in, so I'm looking for a way to hook the sql statement creation process, so that my existing statements like this:

Dim db as New DataContext
Dim query = From obj in db.Objects

will resolve to the TBL_OBJECT_NEW table instead of the TBL_OBJECT table. If I can do this, I can reuse a huge amount of code. I know it's a somewhat unusual scenario, but I'm really hoping it's possible. Any help much appreciated! Thanks.

By the way, I'm using LinqConnect from DevArt for this; I don't know how much a plain L2E approach will apply to this. On the other hand, if you know how to do it with DevArt but NOT L2E, that would still be very helpful.

1

There are 1 answers

1
Devart On BEST ANSWER

We are not aware of any possibility of having two identical tables mapped to one conceptual entity.

Both in LinqConnect and in Entity Framework there is a solution. For example, you can try switching between two models having only one difference (the first model will map TBL_OBJECT, the second - TBK_OBJECT_NEW).

LinqConnect solution:

To switch between different tables with the same structure in LinqConnect, you can create two .lqml files and load mapping from one of them for the current DataContext instance:

string mappingFileName;
if (...) // Check whether TBL_OBJECT_A should be used
  mappingFileName = "MyDataContext_A.lqml";
else 
  mappingFileName = "MyDataContext_B.lqml";
Stream contextStream = System.IO.File.OpenRead(mappingFileName);
System.Data.Linq.Mapping.MappingSource mappingSource =
Devart.Data.Linq.Mapping.XmlMappingSource.FromStream(contextStream);
MyDataContext context = new MyDataContext(connectionString, mappingSource);

Also, we plan to support fluent mapping (the approach when mapping is set in your code without using attributes or mapping files), though cannot provide any timeframe for this at the moment. You can vote for this feature at our UserVoice.

Entity Framework solution:

Set the Metadata Artifact Processing property to CopyToOutputDirectory. After this go to the generated SSDL files and change the table name from "TBL_OBJECT" to "TBL_OBJECT_NEW". The only thing now is to create the context with the correct connection string (you can either add a new connection string to the application configuration file or pass the entire connection string to the ObjectContext constructor).