I have been tasked with upgrading our software to use EF6. Previously it was using a combination of EF4 & 5.
We use the database first approach. The upgrade went smoothly as far a code changes go, but after running the application and doing a query the following error is thrown.
Schema specified is not valid. Errors:
The mapping of CLR type to EDM type is ambiguous because multiple CLR types match the EDM type 'tblAccountMaintenance'.
Previously found CLR type 'DALUsers.StatusDB.tblAccountMaintenance', newly found CLR type 'DALUsers.AccountsDB.tblAccountMaintenance'.
The class in questions, tblAccountMaintenance, is generated inside multiple .tt files. The classes are references to the same table, just referenced in different .edmx files.
Simply removing one of the references is not a good option in this case as we have used a similar strategy with several other tables and would require thousands of lines of rewritten code.
What do I need to do to fix this in EF6?
So it turns out the the issue (using the same tables, with the same name in multiple edmx files in the same project) is related to the fact the the .tt files contain new objects that derive from dbContext - and this is a limitation/constraint that is specific to dbContext.
I downloaded this plugin: https://visualstudiogallery.msdn.microsoft.com/66612113-549c-4a9e-a14a-f629ceb3f89a
Which allows me to create EF6 .tt files that derive from EnityObject instead which does not have this constraint. It also makes it so I don't have to update all of my code to use the newer dbContext methods which is a plus.
As a note to others viewing this - this is probably not the best answer if you are starting with a newer project or have a small number of edmx files/tables as EntityObject is not as robust as dbContext, however this is a good band-aid fix - especially if you are like me and going to have to do a complete rewrite when EF7 comes out.
Related
I'm using Visual Studio 2013 and Entity Framework 6.1.3 against a legacy Oracle 12c database to generate a database first EDMX model. The problem I'm encountering is that for some tables, only a Storage Model definition of the table is generated, but it should be generating both a Storage Model definition and a Conceptual Model definition. Without the conceptual model definition, C# classes are not getting generated, so I can't use the tables.
Info about the tools that I'm using:
Visual Studio 2013 v. 12.0
.NET 4.5.2
Entity Framework 6.1.3
Oracle 12c
Offical Oracle ODP.NET, Managed Driver 12.1.2400
Official Oracle ODP.NET, Managed Entity Framework Driver v.12.1.2400
I've been trying to figure out how to fix this for a couple days now. I've only found one reported instance on the web that even comes close to what's happening to me (https://www.codeproject.com/Questions/1102413/EF-doesnt-add-all-tables-in-conceptual-model), but there is no reported solution to that problem.
The EDMX that I'm trying to add the tables to currently holds about forty table definitions. The interesting thing is that I can create a separate, empty EDMX file and successfully add my problem tables sometime, but not all the time. I was thinking about generating the definitions for my tables in the separate EDMX and then copying them to the original EDMX, but I'm not confident that I would successfully include all of the necessary markup, especially when trying to include navigation links between other tables. Also, this would be horrible to have to do every time I encounter a table that has this problem.
Various solutions to EF problems say to "Run the Custom Tool", but that won't work in this case because of the missing conceptual model information.
Thanks for any help.
I finally figured out what was happening. One of the "problem" tables was not actually a problem, just my misunderstanding of how Entity Framework works. This table was a pure join table having only two columns: one column pointing to table A and the other to table B. Entity Framework does not generate a class for a pure join table. Instead, it just converts it to navigation links on the classes of the two joined tables (class A and class B).
The problem with the second table was real, and was caused by mismatched column definitions in the database. A foreign key definition had a column of type NUMBER(18) on one side and a column of type NUMBER(22) on the other. EF was converting the NUMBER(18) to long, and the NUMBER(22) to decimal. EF apparently does NOT like having differing C# types on the ends of its navigation links.
To resolve the problem, I modified my EDM number mapping (see https://docs.oracle.com/cd/E56485_01/win.121/e55744/entityDataTypeMapping.htm#BABGBJCI) so that NUMBER(18) and NUMBER(22) both resolved to long. I then removed all of my table definitions from the EF Designer and re-added them so that all of my field types would regenerate. I assume I could have also resolved the problem by fixing the mismatched types in the database, but I found the same problem in a couple dozen more places, so I went with the code solution.
Maybe an odd question, but we have a scenario in which we want to use Entity Framework code-first in an environment which could have a database with a newer/higher version than the code itself.
Let me elaborate a bit. We have a couple of solutions which all use a core assembly which contains the overall datamodel which all solutions are using. The solutions are mainly sites and apps which are deployed to several different Azure Web Sites. So the solution are running next to each other. The only thing they are sharing is the Azure database.
Now the scenario will come in play. When we update the database model in the core assembly and update one of the solutions in Azure. The underlying database will be updated when the model is loaded within that solution. No problem there, works like a charm...
The problem starts when one of the other solutions is loaded. These other solution are still using the previous core assembly which has now an outdated EF CF model compared to the database model they are connecting with. So a nice exception will be throw as shown below.
The model backing the '{NAME}' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the DropCreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data.
The question is whether we can force the model just to load and ignore the changes made within the database. We internally have a policy to only apply not breaking changes within the database, so the model should be able to load without any problems.
Thanks in advance for the information and tips!
I can be wrong(not sure whether I remember correctly), but if it doesn't interferes with your application configuration, you can set DB initializer to null:
public PortalDbContext()
: base("name=PortalConnectionString")
{
Database.SetInitializer<PortalDbContext>(null);
}
Or it could be possible to create custom initializer:
public class BlogContextCustomInitializer : IDatabaseInitializer<BlogContext>
{
public void InitializeDatabase(BlogContext context)
{
if (context.Database.Exists())
{
if (!context.Database.CompatibleWithModel(true))
{
// Do something...
}
}
}
}
If you're using EF Code-First, the model must match the database.
Even if you found a way to circumvent that limitation you'd be doing something dangerous.
Let me expalin it: if you update the database from "Solution A", the model in "A" will match the database, and any further changes to the model in this solution can be applied to the database without any problem at all. That's right!. However, if you do what you're asking in this question, i.e. you do something so that "Solution B" can keep working even if the model doesn't mathc with the DB, and then you make a change to the model in "Solution B", how do you apply it? how can "Solution B" know what changes to apply? how can "B" determine what changes made by "A" should be left as they are, and what are the new changes made by "B" that must be applied to the database?
If you could follow on like this, you'd finish with two different code first models, none of which matches the database, and, besides, how could you warranty that both applications work correctly? how can you ensure that changes on "A" doesn't affect code on "B" and viceversa?
The safest solution to avoid this problem is to share the assembly containing the code first model between both solutions. Any other solution will be troublesome sooner or later. Perhaps you'll have to refactor your solutions so that they can share the same DbContext. The DbContext must be the only thing in your project. I usually have an Entities project, and a DbContext project which has a reference to Entities. Then both solutions would have references to these projects. These projects can be in one of the solutions, or in a completely different solution. Of course in one, or both solutions, you'll have to add a reference to the DbContext assembly, instead of the project, and keep it updated, for which you can use post-build scripts. In this way, when you recompile your solutions you'll also detect incompatible changes made for one solution which adversely affects the other.
EF6 supports several different DbContexts in the same database, so, if each of your applications had a different, non conflicting DbContext, you wouldn't have a problem. I cannot check it right know, but I think that the name of the DbContext must be different in each solution (I don't remember if the namespaces are taken into account). By non conflicting I mean that they refer to different database objects (tables, views, or whichever), of that the objects refered to by both contexts are not changed (for example master tables).
This does not seem to be explicitly listed as a feature in any of the sparse examples I can find, for example:
http://blogs.msdn.com/b/adonet/archive/2011/01/27/using-dbcontext-in-ef-feature-ctp5-part-1-introduction-and-model.aspx
http://www.codeproject.com/Articles/336187/code-first-practical-case
or
http://blogs.msdn.com/b/adonet/archive/2011/09/28/ef-4-2-code-first-walkthrough.aspx
But I think the DbContext docs at least imply that it's possible:
http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext(v=vs.103).aspx
DbContext is usually used with a derived type that contains
DbSet properties for the root entities of the model. These
sets are automatically initialized when the instance of the derived
class is created.
My goal is to use the EF to access a DB through a WCF data service from a Silverlight client, where the some of the columns are unknown at runtime. Any better ideas would be appreciated
Neither WCF or EF is suitable technology for this situation. WCF and its autogenerated proxies expects compile time defined model - you can avoid this but as a result you will not work with strongly typed data contracts but with "generic data" and you will work with them on XML or JSON level.
In case of EF it is even worse there is no easy workaround to get dynamic behavior. You can change DB or even mapping (but not with code first - only with EDMX) in dynamic way but still at the end you need compiled classes representing your mapped data.
The part of documentation you are referencing is not about dynamic creation of mapping but only about dynamic initialization of mapping defined in design time.
If anyone is interested, here is a synopsis of how to change the EDMX files to match a DB discovered at runtime:
Get and parse schema from the database (simple XML)
Put the schema in a format that is comparable with the EDMX metadata (more complex XML)
Use a tool like this one: http://efmodeladapter.codeplex.com/ to make the changes to the metadata (some assembly required)
Instantiate the data model
There is a commercial tool to do the same, but it's not free: http://huagati.com/dbmltools/
And here is the best list of other, more palatable options: Modifying an Entity Framework Model at Run-Time
Our product is partially built using Delphi and partially .NET and in our current state of migration to .NET, we have the data dictionary in a Delphi component, so this is the master.
From this we generate .NET source code through templating, to support simple querying but also to do Linq2Sql, since our product requires SQL Server.
However, I'd like to switch to the new Entity model in .NET instead of Linq2Sql, but I don't know how much work that would be. All the tutorials or examples I find seem to revolve around modelling the data model in the designer, or getting it from the database, neither works for our needs.
In Linq2Sql, we annotated our query-classes with TableMappingAttribute and ColumnMappingAttribute, and then generated a descendant of DataContext, this all works very well.
Is there a similar easy path to get to use the Entity model code instead? Or do I have to produce all those xml files and run tools to produce resources, etc.?
Has anyone been in the same situation and can shed some light on this?
Unfortunately for you I think you do need the XML files.
There are actually 3 files that make up the EDM. (although in visual studio they are all combined into 1 EDMX file)
ssdl - storage (Describes the database)
csdl - conceptual (Describes data objects)
msl - mapping (Describes the mapping between storage and conceptual)
From the EDM files, the EDM Generator can be used to generate all three from a database connection, just the msl and csdl from the ssdl, or it can generate the actual data objects from the csdl.
Unfortunately though, that isn't where the usage of the XML stops. It is still needed at runtime for the entity framework to perform the translation from objects to storage etc. A reference to the 3 EDM files must be provided in the Entity framework connection string. (More info on building EF connection strings)
You could probably come up with ways to have your data object code generated (or automatically tag your existing ones with the various required attributes and extra methods) - like Linq there are attributes like EdmEntityTypeAttribute and EdmScalarPropertyAttribute that are put on the classes and properties, but without the 3 EDM files the entity framework isn't going to know what to do with your data objects. The generator also adds other stuff to the data objects classes like property changed events, and an inheritance from EntityObject. I'm not sure what of the extra stuff is required for correct operation of the entity framework, and what is just there for the developer. I would assume the property changes events are required by the data context to track changes.
There's an article here on EDM tools and some code for generating/splitting EDMX files into their component ssdl/csdl/msl files.
I've begun experimenting with LINQ to SQL and what I am doing is basically creating classes with LINQ mapping decorators - thereby choosing which parts of the db table schema I want to incorporate into my classes.
A simple example:
private DateTime? _LocalCopyTimestamp = (DateTime)SqlDateTime.MinValue;
[Column(Name = "recaLocalCopyTimestamp", Storage = "_LocalCopyTimestamp", CanBeNull = true)]
public DateTime? LocalCopyTimestamp
{
get
{
return this._LocalCopyTimestamp;
}
set
{
this._LocalCopyTimestamp = value;
}
}
I am not using and am not willing to resort to modeling tools due to project contraints (the way schema changes are handled and because there is an existing database schema and it is a bit too organic and non-strict)
Is there a way to have this flexibility with the Entity Framework without having to include schema information files and/or lots of distinct code files?
Could I then also create classes that "use" more than one underlying table?
Can anyone point me to documentation regarding this?
The feature you are requesting (write C# classes and generate your model from those) is termed by the Entity Framework team "Model First." It does not exist in the current, shipping version of the Entity Framework, but is a planned feature for the next version. If you watch the Entity Framework talks from PDC, you can see demonstrations of this new feature. With the current version, you do not have to write "many" mapping files, but you do need one (the EDMX file), and it must be XML.
Yes, you can create entity classes which use more than one underlying table. This is called "Entity splitting." Step-by-step instructions at the link. In general, you will find that the Entity Framework supports many more complicated mapping scenarios than LINQ to SQL.
I'm afraid that I have to completely disagree with Marc regarding writing EDMX without use of the designer. Writing EDMX without using the designer is not only possible, but for projects exceeding a certain side, it is all but inevitable. A few points on this:
For most of the early history (pre-RTM; "ObjectSpaces") of the Entity Framework, writing the XML files manually was the only way to use the tool. The designer is a recent feature, and is considerably less stable than the Entity Framework itself.
There are certain Entity Framework features, such as complex types, which are not supported in the designer at all.
Certain mapping scenarios, such as not mapping individual columns, or mapping tables without a foreign key relationship, which may be necessary for legacy databases, are not supported in the designer.
As I mentioned in (1) the designer is quite a bit buggier than the Entity Framework itself. So on larger projects you will probably end up having to clean up after the designer's mistakes.
Entity Framework uses the EDM to model data; this is a set of 3 complex schema files (storage, conceptual, mapping), most commonly stored as resources in the project (via the designer which uses a single EDMX file to generate all 3 schema files).
It doesn't support attributed classes for this information. The only sensible way to write EDM is via the designer (essentially, a modelling tool which you dislike).
Re classes the "use" more than one underlying table; yes, a single Entity Framework entity at the conceptual layer (i.e. classes) can span multiple storage tables. This is especially useful for some inheritance examples, but can (IIRC) be used by flat models too. You do this via the "mappings" between the storage and conceptual layers (most commonly; on the tab in the designer).