I have a frustrating situation owing to this little quirk of EF. Here's a simple demo of the behavior. First the DB schema:
As you see, RestrictedProduct is a special case of product, which I'm intending to make a subclass of Product with some special code.
Now I import to an EF data model:
Oops! EF saw that RestrictedProduct had only 2 fields, both FKs, so it mapped it as a one-to-many relationship between Product and Restriction. So I go back to the database and add a Dummy field to RestrictedProduct, and now my EF model looks much better:
But that Dummy field is silly and pointless. Maybe I could delete it? I blow away the field from the DB table and the entity model, then refresh the model from the DB...
Oh, no! The Product-Restriction association is back, under a new name (RestrictedProduct1)! Plus, it won't compile:
Error 3034: Problem in mapping fragments starting at lines (x, y) :Two entities with possibly different keys are mapped to the same row. Ensure these two mapping fragments map both ends of the AssociationSet to the corresponding columns.
Is there any way to prevent this behavior, short of keeping the Dummy field on the RestrictedProduct table?
I just came across the same issue, and as an alternative to putting the dummy field in your RestrictedProduct table to force the creation of an entity you can also make your RestrictedProduct.RestrictionId field nullable and EF will then generate an entity for it. You can then modify it to use inheritance and any subsequent "Update model from database" will not cause undesired nav properties. Not really a nice solution but a work around.
Let's walk slowly into your problem.
1st thing you need to decide is if the restricted product is
really a special case of product or is it a possible extension
to each product.
From your original DB Scheme it seems that any product may have
a relation to a single restriction however a single restriction
can be shared among many products.. so this is a simple 1 to many
situation which means that restricted product is NOT a special case
of product! Restriction is an independent entity which has nothing
to do with product in a specific way.
Therefore EF is correct in the 1st importation of your scheme:
1. a product can have 0 or 1 restrictions.
2. a restriction is another entity which can be related to many products.
I do not see your problem.
Related
We have a database in which one table contains records that can be child to several other tables. It has a "soft" foreign key consisting of the owner's Id and a table name. This (anti) pattern is know as "polymorphic associations". We know it's not the best database design ever and we will change it in due time, but not in the near future. Let me show a simplified example:
Both Event, Person, and Product have records in Comment. As you see, there are no hard FK constraints.
In Entity Framework it is possible to support this model by sublassing Comment into EventComment etc. and let Event have an EventComments collection, etc.:
The subclasses and the associations are added manually after generating the basic model from the database. OwnerCode is the discriminator in this TPH model. Please note that Event, Person, and Product are completely different entities. It does not make sense to have a common base class for them.
This is database-first. Our real-life model works like this, no problem.
OK. Now we want to move to code-first. So I started out reverse-engineering the database into a code first model (EF Power Tools) and went on creating the subclasses and mapping the associations and inheritance. Tried to connect to the model in Linqpad. That's when the trouble started.
When trying to execute a query with this model it throws an InvalidOperationExeception
The foreign key component 'OwnerId' is not a declared property on type 'EventComment'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.
This happens when I have bidirectional associations and OwnerId is mapped as a property in Comment. The mapping in my EventMap class (EntityTypeConfiguration<Event>) looks like this:
this.HasMany(x => x.Comments).WithRequired(c => c.Event)
.HasForeignKey(c => c.OwnerId);
So I tried to map the association without OwnerId in the model:
this.HasMany(x => x.Comments).WithRequired().Map(m => m.MapKey("OwnerId"));
This throws a MetaDataException
Schema specified is not valid. Errors:
(10,6) : error 0019: Each property name in a type must be unique. Property name 'OwnerId' was already defined.
(11,6) : error 0019: Each property name in a type must be unique. Property name 'OwnerId' was already defined.
If I remove two of the three entity-comment associations it is OK, but of course that's not a cure.
Some further details:
It is possible to create a working DbContext model ("code second") from the edmx by adding a DbContext generator item. (this would be a work-around for the time being).
When I export the working code-first model (with one association) to edmx (EdmxWriter) the association appears to be in the storage model, whereas in the original edmx they are part of the conceptual model.
So, how can I create this model code-first? I think the key is how to instruct code-first to map the associations in the conceptual model, not the storage model.
I personally stick with Database first when using EF on any schema that is this level of complexity. I have had issues with complex schemas in regards to code first. Maybe the newer versions are a little better, but worrying how to try and code complex relationships seems less straight forward then allowing the engine to generate it for you. Also when a relationship gets this complex I tend to avoid trying to generate it with EF and try and use stored procedures for easier troubleshooting of performance bottlenecks that can arise.
OK, this is an interesting and most importably real urgent problem for me to solve... In order for others to neatly comprehend it, I've stretched myself to make a well illustrated post.
The Object Model
So I have this simple, easy and "beautiful" model in mind. See the first picture. (You can ignore PathEntry, it's not relevant in my situation.)
The idea is that a MediaFeedItem owns:
a collection of ThumbnailFileEntries (accesible through the ThumbnailFiles property)
at most 1 raw FileEntry (MetadataFile property) and
at most 1 MediaFileEntry (MediaFile property)
We shall refer to these last three entity types as the file entities.
Now there's more: As you can see, I am inheriting both ThumbnailFileEntry and MediaFileEntry from FileEntry, and let's not debate that! (for now), it's one of those end-of-story aspects of the design and both entity types will continue to grow later on.
This already brings me some significant issues right away in regards to the polymorphic associations induced by the relationships from the file entities to MediaFeedItem.
The first thing that you shall observe is that I have eliminated the navigation property from the derived file entities (ThumbnailFileEntry and MediaFileEntry) to the primary entity MediaFeedItem.
I do this because they already inherit that property defined in the base class FileEntry. As you can see, I do not delete the roles at the end of these associations.
The Relational Model
I shall be using the so-vastly-conceptually-superior TPT strategy for generating and mapping my Object Model to the RDB world (vs TPH/TPC).
I'm using EF5-rc, the EDMX model designer to design my model, and the EF5 DbContext Generator to generate a DbContext and POCOs cuz I wanna use the DbContext API.
As you can see, I can nicely generate the database model using the EF tools:
The Problem
When loading a new MediaFeedItem and saving it, I get the following error:
System.InvalidOperationException: Multicplicity constraint violated. The role 'MetadataFile' of the relationship 'MediaFeedModel.MediaFeedItem_MetadataFile' has multiplicity 1 or 0..1.
What am I doing wrong?
Looking at your problem one thing stands out, The FK relationship between File and MediaFeedItem is required (IE a file must have a MediaFeedItem), but in the case where you are in an extended version of File you probably dont want this.
What i think you want to do is one of the following:
change the multiplicity on MediaFeedItem_FileEntry to 0..1 - 0..1 so that it isnt required at either end
create a new extended type to handle your metadataFile type and remove the direct reference between the base type and MediaFeedItem
I personally think the second is a more elegant solution to your problem as its creating an actual type for your MetadataFile
What appears to be happening is that you are trying to create an extended type but the base type isnt actually a metadata file.
Such a task: we have 2 tables in our L2S Entity classes. It needs to manage with current fields of current tables by numbering em somehow.
Exact question is How can I point to the exact field of exact table without using entity relation names? Such as TmpLinqTable[2] instead of TmpLinqTable.TableField.
Moreover if it can be managed by ids of the entity, not the table.
So my understanding of what you are trying to do is to log changes that happen to your entites. Is that correct? You might want to look into the GetModifedMembers method on the Table class. Here's an interesting link...
http://geekswithblogs.net/steveclements/archive/2008/04/15/linq-to-sql-property-changed--changing-logging.aspx
I am trying to come up with a database design that would work with Entity Framework 4 Code First. Actually, I have no experience yet of EF4 Code First but as I understand it, if I write the code, it will create the database and tables.
The issue is this. There are various types of auctions, they all have some common fields and some specific ones. In the code I envisage having a base abstract class called Auction and subclasses like LowestUniqueBidAuction and EnglishForwardAuction etc.
Nothing surprising there. The problem is that I imagine the database structure to mimic this. I imagine an Auction table and a LowestUniqueBidAuction table and a EnglishForwardAuction table. In the Auction table I imagine a foreign key into one of these two tables for each row depending on the type of auction that that row is. I also imagine another column in the Auction table with the name of the derived auction table (such as EnglishForwardAuction).
The problem is that whenever I've ever created a foreign key I've had to specify the name of the foreign table into which the key points (which makes sense). In this case, however, there is one of many tables that the key could point. So there are many issues here. Firstly, I could simply not use a foreign key and just use an ordinary field, but then the database will not be able to maintain data consistency for me. The second issue is how will EF Code First handle this? In other words, how will it know that if I ask for all EnglishForwardAuction rows from the Auction table that it should look at the column with the table name and then join on the EnglishForwardAuction table to get the extra fields?
Has anyone ever faced similar issues?
Thanks,
Sachin
This problem is solvable in Entity Framework in a number of ways - read up on how EF handles inheritance and what strategies are available.
There are basically three strategies how to handle this:
(1) Table per Hierarchy
You have only one single table, that represents all possible sub classes. Of course, this means, several rows (that only exist in a given subclass) must be nullable, since they don't show up / don't exist in super classes or other subclasses.
(2) Table per Type
Each subclass gets its own table, and by default, the sub-types table shares the PK with the base classes' table - e.g. PK = 1 in Auction will also be PK = 1 in EnglishForwardAuction. So your subclass tables reference the base table - not the other way around.
(3) Table per Concrete Type
Each concrete subclass (your separate auction types) gets its own table, but that table contains everything - all the columns, from that specific type, but also its base type.
Read more here:
Inheritance in the Entity Framework
Inheritance and Associations with Entity Framework Part 1
Entity Framework Modeling: Table Per Hierarchy Inheritance
Entity Framework Modeling: Table Per Type Inheritance
Searching for Entity Framework Inheritance and/or one of these strategies will reveal a lot more hits, too - that topic is very well covered and discussed on the interwebs! :-)
I think this is a question of the best technique or best way to skin a cat!
Imagine a menu with items (menu choices) on it. I have a table called MenuItem, which for example "Spaghetti Bolognese", it has lots of other information associated with it aside from just a better description and picture.
Eg.
Basic Information (Name, Description, Picture, etc)
Nutritional Information (approx 15 columns)
Allergy Information (approx 16 columns)
Dietary Information (another 7 columns) (religious etc)
As it is at the moment I have it all in the one table in SQL server, which is logical database design to me as it doesn't repeat, despite it making the field list for the table longer than I would like. I'd already been feeling a bit bad about just continually extending the database table. But now we also want to add 'Recipe' information, approx another 7 columns.
I'm using Entity Framework 4.latest, and feel there is probably functionality to help me split this off within the EDMX? (Is that what ComplexTypes are?) Or do I just need to do this in the ViewModel class I call?
I think what I'm after using in my code to segregate things better is something like
MenuItem.Recipe.Ingredients
MenuItem.Nutrition.Fat
etc
Complex types can help you but be aware that complex types cannot contain navigation properties, cannot be null and are always loaded with the entity. Other possibility is to use table splitting - this will allow you to map multiple one-to-one related entities to the same table. The main features of table splitting are:
Entities can share only primary key properties
There is one main entity and others are considered as relations (navigation properties)
Related entities must exists - they are not optional so when you insert new main entity you must insert these related entities as well even if they are empty
Related entities must be loaded with eager, lazy or explicit loading