I have a situation where a multitude of very similar but not identical legacy databases is being reverse engineered into a C# model using dotnet ef dbcontext scaffold. Due to the variety of the databases there is no single definitive source. The closest one have a column in a couple of tables that should not be in the C# model.
I had a look at https://github.com/dotnet/efcore but could not immediately see options or paths in the code allowing this finegrainedness.
Is there a way to add metadata to the database to skip columns is skipped?
There is currently no way to do this as there is no option for that in scaffolding options
Take a look at DatabaseModelFactoryOptions.cs and EntityFrameworkCore.psm1 for more info
Related
My team has inherited a database application that contains hundreds of tables. The application uses Entity Framework and takes a database first approach for development. Our current process is to pull a table or two at a time into the edmx using the Update Model From Database... tool.
We are considering making a new API with .Net Core, but as far as I can tell from the research I have done, there is no equivalent process in the Entity Framework Core tools. The closest thing I can find is to reverse engineer the entire database with Scaffold-DbContext, and then use migrations for all future database changes. We can't scaffold the entire database, because some of the tables have errors, and fixing all those errors is not a viable option for us right now.
I have found that I can supply a list of tables that I want scaffolded with the initial Scaffold-DbContext call, but I'm not sure if migrations can be used in a similar way to the Update Model From Database... tool. Can I use migrations to add tables that already exist in our database? If not, what other options should I be looking at?
I am working with EF6, MSSQL, Oracle, .NET4.5 on a system that is used globally across company (many departments) to query different databases that belong to our department, that have mostly same EF model, some databases are Oracle and some are Microsoft SQL, some are development or uat, some are logs.
I am using different EF models for Oracle and for MSSQL databases.
One requirement is to switch between databases at run time, and this is easy,
public AggregatorEntities(string connectionString)
: base(connectionString)
{
}
however it does have side effects - many databases (dev, uat, dr, logs,...) are out of sync from what Live is (model is generated from Live), which results in errors when querying those databases.
Management knows about situation and they are ok for devs that work on some specific database to do changes to global querying system that would allow testers and uat to query the data. However they want changes they have to do to take minimum time to do this - as it is additional cost to each project that involves database changes. I will basically need to build a 'can handle all' resilient system, that when one changes database in EF will do something to accommodate to specific database.
There are different failure scenarios:
1. Name of column on table is the same but Type is different in entity
2. No column on table but there is one on entity in EF
3. Additional columns on table that are not on EF
4. Additional tables in database that are not in EF model
5. No table in database but there is entity in EF model.
I have done some thinking and this question is broad and might get closed for same reason. However I am not sure if it is worth splitting the question into each scenario, as it depends on the answer. The way I understand if single answer can answer all points then no need to split, however if each situation has different 'cure' then question should be split for that part only, but without answer no way to know.... (catch 22).
Only option I see ATM is to generate it's own model for each mirroring database, but then I end up with 50+ models.
How do I allow EF to work with different database structures at run-time?
This now officially cannot be done in a proper manner.
However end result of being able to switch between different databases with similar structures still can be achieved (for those without morals). Part with removing columns can used.
Solution is to have all inclusive EF model that is generated from database that has all the tables and all the columns (that are in any database think like logical OR of everything). Then model with all entities that have all properties from all db environments can be removed specific to environment that is queried at runtime in mechanism described here. This does not cover cases where type of column changes.
Hope this saves you some time as it took 2 weeks from mine...
I have a MVC web application that I've done code first to build my database.
I also need to have a console app manage data based on timeframes so, it will also need to access this database which I understand I can use as a Database First model.
However, I also need to build another website as a management dashboard, which I understand will also work as Database First.
Can I do this without having EF in one of the two circumstances nuke the database if I need to make a change to the model?
The short answer: no. You cannot implement both code-first and data-first EF on the same dataset without encountering a bona fide logistical nightmare.
Converting from one to the other is not quite as difficult as you might think, however, if your application is not overly complex. Based on the tables you've already created, data-first EF should produce objects that are reasonably compatible with your existing code.
Your next steps should look like this:
Pick one approach for EF
If necessary, convert existing projects to that paradigm
Move EF code into a shared class library (as suggested by snow)
Implement new projects using that class library to ensure consistency and reduce redundancy
I am very new to entity framework and I am trying to do something like following scenario.
I am creating ASP.net web from application. That website needs to connect to two databases which the schemas are completely different.
I have no idea how the basic structure should be.
I though of have EF on class library. please guide me with instructions since I have less knowledge.
Since you are using two different databases, the only viable option is to create two separate conceptual models. Even if you would be able to merge two different databases into a single conceptual model, it would be a pain to maintain is the databases are of mentionable sizes.
The two models could reside within the same project, in seprate folders to get different namespaces.
E.g.:
Company.MyApp.DataModel
Company.MyApp.DataModel.Model1
Company.MyApp.DataModel.Model2
Then you could put a new layer on top of these two models which do all the heavy lifting, and could even make them look like one database if you want that, or merge data from entities in both models into a DTO or something similar.
Check out the Repository pattern.
If you think about it, when you create a EDM model with Visual Studio it ask you to give an existing database, and when finished creating the model, it generates an EF connection string, that internally address to the given underlying database connection string.
E.g: metadata=res:///EFTestModel.csdl|res:///EFTestModel.ssdl|res:///EFTestModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.\;Initial Catalog=EFTest;Integrated Security=True;MultipleActiveResultSets=True"*
So each model matches only a database, only a connection string.
EF4 still does not support creating one conceptual model which works with N storage models. At least this is not supported with any built-in provider. Perhaps in the future this could be done through a new provider that combines the support of many storages (from the same providers or different).
I havent done enough research on it, but perhaps Windows Server AppFabric (Codename Velocity) could be the bridge to go through this gap.
Note: I have tried even editing manually the xml for the EDM (edmx) to insert a second element inside the tag but it does not match the EDM XML Schema so VS warns about it: Error 10021: Duplicated Schema element encountered.
You are going to use model first approach as the database already exists.
You will need to create two edmx for the two database.
You can create one model project which you can have connection strings for both the edmx in the app.config file and then create your edmx.
I started a new project C#, and I used the "enable-migrations" command in the package console window. This naturally added migrations to my project. I then set automatic migrations to true, so that as I call "update-database" it will create my tables for me with all keys and that.
The only problem is that I have multiple websites where want to do this, which all use the ASP.NET membership provider to login. Which through automatic code migrations create a bunch of account tables for me to use. But the tables are all called the same, so if I do this targeting the same database for different sites they will overwrite eachother. So the question I got is this: How can I specify a prefix for my tables created by the entity framework?
I've seen several ideas on how to do this while searching, but they didn't work for me (the necessary properties wasn't there for some reason and so on.)
Thank you
Xenoxsis
I'm not sure how do you plan to do just that - if I'm getting it right you'd want to keep one database (shared) in between number of web sites - yet, have each site has its own membership tables, named differently, with different prefixes, right?
First problem is that for each Db/table name change - you need a 'code to match' - i.e. code first entities and code, the 'migration table' in the Db - and tables are all in sync - so it could all work together as it should. In that sense, just changing script or table names in Db won't work. It has to be done at the level of attributes (as #Steven suggested) or fluent configuration.
Which in your case, it means that somehow you'd need to 'build' separate configurations for each site, deploy them separately (code) to each site - and build one mega Db that contains all the small variants of each merged together.
That's going to be tough to manage - but you could try (what I described above) - I have no idea if it'd work (as this requires lot of 'infrastructure' to try this one) - but maybe along these lines...
put Table attributes (or via fluent config)
Build code - 'vary' the Table names for each - and rebuild (ideally you might need to employ some tool, code-generator to do this automatically in a batch - i.e. you build, copy files externally, change names and repeat)
Build 'migrations' for each case (Table name) also - save migrations
as files - and also do Update-Database -Script to save the actual
scripts for each case (important).
Save each migration - or we can
say a 'script' to represent.
Once done - you'd need to merge the
migrations - scripts - into one big master script - i.e. remove the
identical set of tables (leave just one of course) - and copy all
different sets for membership tables.
Remove the migration table
from the database - as that'd surely be out of sync and won't let you
do anything (or there is also a flag in code I think to just ignore
that, don't have it right now). For details see below in my other
post.
Deploy one master Db - using script you created
Deploy the
specific code - to each of the sites.
Pray it'd all work :)
There must be something smarter - but on the other hand, migrations are not made to work for such scenarios, so it's going to be hard if not impossible to pull this off.
Some general info that might help...
How to synchronize migrations with existing databases - geared toward production scenarios, maintaining Db-s and CF to match. It's not exactly what you need but has a detailed description, possible ways to resolve this which I wrote a while ago...
MVC3 and Code First Migrations - "model backing the 'blah' context has changed since the database was created"
To summarize...
What works for me is to use Update-Database -Script
That creates a script with a 'migration difference', which you can
manually apply as an SQL script on the target server database (and you
should get the right migration table rows inserted etc.).
If that still doesn't work - you can still do two things...(more inside)...
I don't know of anyway to make Entity Framework do this automatically across all entities. But you could force a table name, or schema using attributes or fluent API to get the desired effect. For example:
[Table("[put prefix here]_Users", Schema = "[put schema here]")]
public class User {
// ...
}