How-to edit EDMX programmatically - entity-framework

I'm using a database-first process. I've got hundreds of tables imported into my EDMX and generated CUD procs imported as well. The generated CUD procs use a naming convention based on the table name and he CUD operation.
How can I write some code to open the EDMX, associate the CUD procs with the proper entities, and save the EDMX?
This is a lazy-developer, design-time task - this will not be happening at runtime.

Well, what I wanted was a free library which contained the object-model representation of the EDMX. This would allow developers to edmx.Load(pathToEdmx), query the object-model, make changes, and edmx.Save(). Apparently, such a library doesn't exist.
So, I wrote some code to load the XML, query the XML, make some changes, and save. Not as rich as an object-model with validation and helpful exceptions (and very prone to typos), but it worked.

Related

Combine Code First & Database First In Single Model?

Is there a way to combine code-first and database-first in the same context? We are running into massive development-time performance problems when editing the EDMX file (it takes 1.5 minutes to save). I've moved our non-insert/update/delete UDFs/stored procs to some custom T4 templates that automatically generate model-first code, but I can't seem to get OnModelCreating to be called when EDMX is involved.
Other things we've considered, but won't work for one reason or another:
We can't (reasonably) separate our code to multiple contexts as there is a lot of overlap in our entity relationships. It also seems like quite a people who have gone this route regret it.
We tried having 2 different contexts, but there are quite a few joins between Entities & UDFs. This may be our last hope, but I'd REALLY like to avoid it.
We can't switch to Dapper since we have unfortunately made heavy use of IQueryable.
We tried to go completely to Code-First, but there are features that we are using in EDMX that aren't supported (mostly related to insert/update/delete stored procedure mapping).
Take a look at the following link. I answered another question in a similar fashion:
How to use Repository pattern using Database first approach in entity framework
As I mentioned in that post, I would personally try to switch to a Code First approach and get rid of the EDMX files as it is already deprecated and most importantly, the maintenance effort is considerable and much more complex compared with the Code First approach.
It is not that hard switching to Code First from a Model First approach. Some steps and images down below:
Display all files at the project level and expand the EDMX file. You will notice that the EDMX file has a .TT file which will have several files nested, the Model Context and POCO clases between them as .cs or .vb classes (depending on the language you are using). See image down below:
Unload the project, right click and then edit.
See the image below, notice the dependencies between the context and the TT file
Remove the dependencies, the xml element should look like the image below:
Repeat the procedure for the Model classes (The ones with the model definition)
Reload your project, remove the EDMX file(s)
You will probably need to do some tweeks and update names/references.
I did this a few times in the past and it worked flawlessly on production. You can also look for tools that do this conversion for you.
This might be a good opportunity for you to rethink the architecture as well.
BTW: Bullet point 4 shouldn't be a show stopper for you. You can map/use Stored Procedures via EF. Look at the following link:
How to call Stored Procedure in Entity Framework 6 (Code-First)?
It also seems like quite a people who have gone this route [multiple contexts] regret it.
I'm not one of them.
Your core problem is a context that gets too large. So break it up. I know that inevitably there will be entities that should be shared among several contexts, which may give rise to duplicate class names. An easy way to solve this is to rename the classes into their context-specific names.
For example, I have an ApplicationUser table (who hasn't) that maps to a class with the same name in the main context, but to a class AuthorizationUser in my AuthorizationContext, or ReportingUser in a ReportingContext. This isn't a problem at all. Most use cases revolve around one context type anyway, so it's impossible to get confused.
I even have specialized contexts that work on the same data as other contexts, but in a more economical way. For example, a context that doesn't map to calculated columns in the database, so there are no reads after inserts and updates (apart from identity values).
So I'd recommend to go for it, because ...
Is there a way to combine code-first and database-first in the same context?
No, there isn't. Both approaches have different ways of building the DbModel (containing the store model, the class model, and the mappings between both). In a generated DbContext you even see that an UnintentionalCodeFirstException is thrown, to drive home that you're not supposed to use that method.
mostly related to insert/update/delete stored procedure mapping
As said in another answer, mapping CUD actions to stored procedures is supported in EF6 code-first.
I got here from a link in your comment on a different question, where you asked:
you mentioned that code-first & database-first is "technically possible" could you explain how to accomplish that?
First, the context of the other question was completely different. The OP there was asking if it was possible to use both database-first and code-first methodologies in the same project, but importantly, not necessarily the same context. My saying that it was "technically possible" applies to the former, not the latter. There is absolutely no way to utilize both code-first and database-first in the same context. Actually, to be a bit more specific, let's say there's no way to utilize an existing database and also migrate that same database with new entities.
The terminology gets a bit confused here due to some unfortunate naming by Microsoft when EF was being developed. Originally, you had just Model-first and Database-first. Both utilized EDMX. The only difference was that Model-first would let you design your entities and create a database from that, while Database-first took an existing database and created entities from that.
With EF 4.1, Code-first was introduced, which discarded EDMX entirely and let you work with POCOs (plain old class objects). However, despite the name, Code-first can and always has been able to work with an existing database or create a new one. Code-first, then is really Model-first and Database-first, combined, minus the horrid EDMX. Recently, the EF team has finally taken it a step further and deprecated EDMX entirely, including both the Model-first and Database-first methodologies. It is not recommended to continue to use either one at this point, and you can expect EDMX support to be dropped entirely in future versions of Visual Studio.
With all that said, let's go with the facts. You cannot both have an existing database and a EF-managed database in a single context. You would at least need two: one for your existing tables and one for those managed by EF. More to the point, these two contexts must reference different databases. If there are any existing tables in an EF-managed database, EF will attempt to remove them. Long and short, you have to segregate your EF-managed stuff from your externally managed stuff, which means you can't create foreign keys between entities in one context and another.
Your only real option here is to just do everything "database-first". In other words, you'll have to just treat your database as existing and manually create new tables, alter columns, etc. without relying on EF migrations at all. In this regard, you should also go ahead and dump the EDMX. Generate all your entities as POCOs and simply disable the database initializer in your context. In other words, Code-first with an existing database. I have additional information, if you need it.
Thank you to everyone for the well thought out and thorough answers.
Many of these other answers assume that the stored procedure mappings in EF Code-First work the same, but they do not. I'm a bit fuzzy on this as it's been about 6 months since I looked at it, but I believe as of EF 6.3 code first stored procedures require that you pass every column from your entity to your insert/update stored procedure and that you only pass the key column(s) to your delete procedure. There isn't an option to pick and choose which columns you can pass. We have a requirement to maintain who deleted a record so we have to pass some additional information besides just a simple key.
That being said, what I ended up doing was using a T4 template to automatically generate my EDMX/Context/Model files from the database (with some additional meta-data). This took our developer time experience down from 1.5 minutes to about 5 seconds.
My hope is EF stored procedure mappings will be improved to achieve parody with EDMX and I can then just code-generate the Code-First mappings and remove the EDMX generation completely.

Development process for Code First Entity Framework and SQL Server Data Tools Database Projects

I have been using Database First Entity Framework (EDMX) and SQL Server Data Tools Database Projects in combination very successfully - change the schema in the database and 'Update Model from Database' to get them into the EDMX. I see though that Entity Framework 7 will be dropping the EDMX format and I am looking for a new process that will allow me to use Code First in Combination with Database Projects.
Lots of my existing development and deployment processes rely on having a database project that contains the schema. This goes in source control is deployed along with the code and is used to update the production database complete with data migration using pre and post deployment scripts. I would be reluctant to drop it.
I would be keen to split one big EDMX into many smaller models as part of this work. This will mean multiple Code First models referencing the same database.
Assuming that I have an existing database and a database project to go with it - I am thinking that I would start by using the following wizard to create an initial set of entity and context classes - I would do this for each of the models.
Add | New Item... | Visual C# Items | Data | ADO.NET Entity Data Model | Code first from database
My problem is - where do I go from there? How do I handle schema changes? As long as I can get the database schema updated, I can use a schema compare operation to get the changes into the project.
These are the options that I am considering.
Make changes in the database and use the wizard from above to regenerate. I guess that I would need to keep any modifications to the entity and/or context classes in partial classes so that they do not get overwritten. Automating this with a list of tables etc to include would be handy. Powershell or T4 Templates maybe? SqlSharpener (suggested by Keith in comments) looks like it might help here. I would also look at disabling all but the checks for database existence and schema compatibility here, as suggested by Steve Green in the comments.
Make changes in code and use migrations to get these changes applied to the database. From what I understand, not having models map cleanly to database schemas (mine don't) might pose problems. I also see some complaints on the net that migrations do not cover all database object types - this was also my experience when I played around with Code First a while back - unique constraints I think were not covered. Has this improved in Entity Framework 7?
Make changes in the database and then use migrations as a kind of comparison between code and the database. See what the differences are and adjust the code to suit. Keep going until there are no differences.
Make changes manually in both code and the database. Obviously, this is not very appealing.
Which of these would be best? Is there anything that I would need to know before trying to implement it? Are there any other, better options?
So the path that we ended up taking was to create some T4 templates that generate both a DbContext and our entities. We provide the entity T4 a list of tables from which to generate entities and have a syntax to indicate that the entity based on one table should inherit from the entity based on another. Custom code goes in partial classes. So our solution looks most like my option 1 from above.
Also, we started out generating fluent configuration in OnModelCreating in the DbContext but have swapped to using attributes on the Entities (where attributes exist - HasPrecision was one that we had to use fluent configuration for). We found that it is more concise and easier to locate the configuration for a property when it is right there decorating that property.

Generating SQL Server Views from EDMX using T4 templates

I'm working with a legacy database that I can't easily create an entity model over because it uses extension tables with what is effectively composite keys and EF only supports single column keys for mapping one entity to multiple tables.
So, what I've decided to do is create updatable views (with INSTEAD OF triggers to handle CRUD operations) over the top of the legacy tables (which cannot be touched) and then have my entity model (either using EF or DevExpress XPO) built on top of the database views. This will also allow me to do stuff like easily add sub-queries in the select clause to retrieve child counts on parent records when retrieving a list of parent records in a single query.
However, I don't particularly want to manually write the SQL for all the views and triggers so I thought I'd use data model defined in the .EDMX file and t4 templates to help me generate the bulk of the T-SQL needed to create the views and the triggers. I thought there would be some template that I could use as the basis for doing this, but seems that's not so easy to find.
Can someone please suggest a t4 template that I could use as the basis where mappings are being retrieved from the .EDMX. Alternatively can anyone advise how to use the StorageMappingItemCollection to retrieve the mapping information from the EDMX file. I know a few people have said that apparently you can't use it or that they just use Linq to Xml, but I would have thought it should certainly be possible to use the StorageMappingItemCollection class as a strongly typed class to access this data.
Any examples of how I could use StorageMappingItemCollection to access mapping info would be very helpful. Thanks.
See http://brewdawg.github.io/Tiraggo.Edmx/ you can install it via NuGet within Visual Studio and it serves up all of the metadata from your EDMX files that Microsoft hides from you, very simple, works great.

Have anyone used Entity Framework with code first approach mixed with Edmx file?

I'm currently assign to a project where their legacy system is designed in a horrible way and it's been too much focus on database design. I trying to put together a new design where the customer can migrate the legacy system bit by bit.
They are currently using EF 4.1 BUT not code first approach with entity descriptive/mapping is located in an edmx file. They do Reverse engineering everytime to want to extend the model (First make changes in database, then reflect them upwards to Model layer through a custom tool).
What I would like to know, if anyone has used BOTH edmx and code first approach with mapping classes. And is there drawbacks to know about?
You can use EDMX and code mapping together only if you have separate context type for each approach (you cannot mix approaches in single context type). That is probably the biggest disadvantage because it leads to more complex code and maintenance.
For example if you need to have some entity in both contexts types to use it with both new and legacy code you must maintain its mapping twice. You must also be very careful about not duplicating entity class itself = your code first must use class generated by custom tool for EDMX but this will not be possible if they are not using POCOs in current solution.
Another problem will be database integrity. If you will need to save changes to both context types in single transaction you will have to use TransactionScope and distributed transaction = MSDTC (each context instance will handle its own database connection).
If you are sure that whole system will be migrated you can probably think about using code first instead of EDMX (but be aware that code first mapping and DbContext generally offers more limited feature set). If you are not sure that you will be able to complete whole migration don't even think about using code first because leaving system in the state where half uses code first and half EDMX will make everything only worse and much more horrible.
Being sure is little bit theoretical because in SW development the only think you can be sure about is that requirements / situation will change. It means that migration should be very carefully considered.
I also was struck with this problem. What I found was that you can model the database and "generate the database from the model" in a "Ado.NET Entity model Project".
But you can not create stored procedures in that project, What only you can do is you can import the stored procedures from the server.
But if you do not want to create stored procedures on the server, you can create another project on VS, "SQl CLR Database Project" and you can code your stored procedures and tigers in that project and deploy them to the server.
then you can again import these stored procedures from the "Ado.NET Entity model Project" by "Update Model From Database".
Like wise you can develop your server project using both approaches(Code first and Model first)
Hope this will add something more :)

extract SQL Server Extended properties as part of EF 4.0 Entites or run stored procedure in T4 template that does

I am looking to see if Extended Properties can be made to be part of Entities in EF 4.0, when the .edmx is generated or updated from the database. I also would like to see an example of running a stored procedure (function) from the .edmx in a T4 template, since I do have a procedure that returns the Extended Prop values.
Thanks
So, a few things to bear in mind here:
The designer is not really extensible, but the provider is. That doesn't really help much because writing an EF provider is not a walk in the park. It's really complex.
The designer-related code, including the bits that relate to metadata, is mostly sealed and internal and almost completely unusable by you.
However, the EDMX file (the XML file itself) is very well documented: http://msdn.microsoft.com/en-us/data/jj650889
... You can freely modify the XML yourself (by hand or through some Add-in or external utility), as long as you stick to the specifications.
The general idea is that you can use your own tool to read the extended properties and change the EDMX XML.
You will be adding "Annotations" to the SSDL (store metadata in the EDMX) elements. These Annotation values will be based on your extended properties of the relative entities in the DB.
Later on, when T4 executes, T4 receives the metadata collections based on the EDMX elements. This metadata will contain the Annotations you previously wrote there. Just about any element can have one or more annotations. You can then add custom code to the T4 template to handle the annotations that are based on your extended properties. The designer will not show the annotations, and you can't manipulate them in the designer, but it should preserve them (won't overwrite them if they are present in the EDMX).
Of course, this would be a lot easier if the designer was extensible, or even if the designer-related code was usable by you. Right now, that's not the case. Most parts of EF are moving to open-source, but the designer is still not there (yet). If the designer ever gets into open source, then you can probably make changes to start using that - and given that the community keeps asking for this kind of feature, I imagine the community will change the source to make it happen anyway. Until then, you have to manually edit the EDMX or write some tool to do it for you.