Entity Framework and Dynamic Schema - c#

I inherited an application that talks to many different client databases.
Most of these tables in the client databases have identical schema - but there are a handful of tables that have extra custom columns that contain tax information (ya - bad idea - I know … I didn't set it up).
These extra columns could be named anything. They are known at runtime as they can be looked up in another table.
I can setup EF to that it will read/write these tables (skipping the dynamic columns) but I really do need this information - as it is tax data.
I think my best route it to have a fixed model with extra properties added that could be filled by these dynamic columns.
How can I get Entity Framework to dynamically read and write these columns without using custom SQL statements on every call?
I can do extra reads and writes to read and write these extra columns separately (using custom sql)… but there must be some way to override EF so that it knows about these extra columns and can handle them correctly.
Any help would be appreciated.

In a first step, you could interrogate the _INFORMATION_SCHEMA_, or other metadata tables directly, to know if the table you want your context to be on has these columns. Based on that information, you can use a different DbContext (generic would probably work) but create it using MappingConfiguration in which you either ignore the columns if they aren't there, or map them to the POCO class your context desires.

Related

Incremental ETL on code first many-to-many association table

I'm setting up a data warehouse (in SQL Server) together with our engineers we got almost everything up and running. Our main application also uses SQL Server as backend, and aims to be code first while using the entity framework. In most tables we added a column like updatedAt to allow for incremental loading to our data warehouse, but there is a many-to-many association table created by the entity framework which we cannot modify. The table consists of two GUID columns with a composite key, so they are not iterable like an incrementing integer or dates. We are now basically figuring out the options on how to enable incremental load on this table, but there is little information to be found.
After searching for a while I mostly came across posts which explained how it's not possible to manually add columns (such as updatedAt) to the association table, such as here Create code first, many to many, with additional fields in association table. Suggestions are to split out the table into two one-to-many tables. We would like to prevent this if possible.
Another potential option would be to turn on change data capture on the server, but that would potentially defeat the purpose of code first in the application.
Another thought was to add a column in the database itself, not in code, with a default value of the current datetime. But that might also be impossible / non compatible with the entity framework, as well as defeating the code first principle.
Are we missing anything? Are there other solutions for this? The ideal solution would be a code first solution, or a solution in the ETL process without affecting the base application, without changing too much. Any suggestions are appreciated.

Entity Framework 6 dynamically populate data without models

I'm currently trying to read data from a table out of SQL server. The table has 10 columns and when i'm reading the base table by itself, everything works out just fine.
The trouble is, there are X number of extra property tables that may or may not go with my base table. Some databases only have the base table with 10 columns, while others have property tables containing more columns that must be joined into the base table in order to properly display the needed data. Is there a way via EF6 to load that data into a queryable source in a decoupled way?
Basically due to the fact that the extra tables are constantly in flux, I cannot rely on generating models for them and using the mapping EF provides. I do have a model for the base table as its 10 columns never change. I also have a mechanism to read the relational information in order to get the names of the property tables and columns that my program needs to display with the base table when they are available.
Any insight is greatly appreciated.
Good old-fashioned ADO.NET does a good job giving you run-time access to arbitrary query results. You can examine the column data types returned in a DataReader or after loaded into a DataTable, and access columns by name or ordinal position.
And you can interop beteween EF (for your design-time models) and ADO.NET tables that vary at runtime.

Entity Framework AddObject to only "INSERT INTO" certain columns

We have a system that will use the same code to communicate with different client databases. These databases will use the same EF Model, but different connection strings.
Our problem is, not every site will be using the same version of our database structure; some might be missing a few columns or contain a few old columns.
If we upgrade the system to the current version, now the database model now has an extra EmergencyContact column. All older databases will now fail, because EF is trying to insert into this column (even though we have not set a value for this property).
Is there a way of telling EF to only use columns for which we have a value for, when it generates the INSERT INTO query?
EF will be fine if your schema has missing columns that are in the real database, but it will not work if you have columns in the schema that are not in the database, and there is no way to fix that.
Your only choice is to use different schemas for different databases, and write code that manages them (ie, only instantiates the version of the context you need).
In the case where your model does not match your database schema, EF will only insert/update the columns in the model. However, if the unknown columns are not null, EF will throw an exception. Also, if you created relational constraints on the unknown columns, of course those will not be created as they are not yet known.
If the persistence layer per site is the only part that changes then I would extract your EF model into it's own version e.g.
DbV1.dll
DbV2.dll
You could then load in the appropriate DLL based on some setting from the client i.e. you could pass information as a custom header e.g.
db-version: 1
There are other more reliable ways, however, I don't know what your current setup is like so it's difficult to answer.

Use same type against two identical tables in EF Code First

I have two tables, Users and TempUsers and I need to do operations on both of them. I already have my users type defined and I want to add it to the DbContext for both tables. Problem is, it either uses convention to map the type name to a table or using the TableAttribute with the table name specified. Either way I can't see how to add two dbsets mapping the type to different table names.
I could duplicate the type using either copy + paste or through a UserBase class and two derived User and TempUser classes. Both ways will work but really in the code I want to deal with Users and not have the complexity of Users and TempUsers in the code. After all it's the repository's responsibly to deal with where to put the user objects and the business logic shouldn't have to deal with it.
Advice would be much appreciated. Thanks!
[Explanation Based On Comments]
The reason I have two tables is because the TempUsers is to support a bulk import/update but though atomic transactions on each user. So externally some active directory export or some such will result in calling a service for each user. I have to create/update users and figure out what ones are not being imported but already exist in my database and then delete them. Would be much simpler to truncate the Users table and write directly to that but the Id's would be different and it would break all the links the users have to different tables, like shipping history for example.
That is not possible. EF cannot map same class twice within same context. Your single User class can be only mapped to Users table or TempUsers table in single context type. You need either two user classes or two different context types (with different mapping configuration) - one providing access to Users table and second providing access to TempUsers table.
This reminds me of my own question: Querying data using Entity Framework from dynamically created table
Actually, you can use EF and ExecuteStoreQuery to retreive objects, but you cannot use the LINQ features of EF.

How to get Nhibernate to handle non existing database columns gracefully

I am working on a project that requires the use of multiple databases that for the most part are completely identical but some columns might be missing. How do you get NHibernate to handle this for instance i have a table with 4 columns an index and 2 data coloumns that will always be availible but a singe customer does not want the column in their database.
as this is part of a legacy application migration i do not have the luxury of dictating the database format or even change the databases. anybody have any ideas of how to do this. I cannot get NHibernate shards to work with this either.
KR
Nicky
I don't know of a way to tell NHibernate to ignore columns that are otherwise mapped.
I would look at creating multiple mappings files for the different databases and then depending on your environment configure your SessionFactory using the correct mapping files.
This may seem like a little more work to setup initially but it makes it very clear that in database X you have columns A-B-C and in database Y you only have columns A-B.

Categories