MapKey vs HasForeignKey Difference - Fluent Api - entity-framework

What is actually the difference between:
this.HasRequired(a => a.Something)
.WithMany()
.Map(a => a.MapKey("SomethingId"));
and
this.HasRequired(a => a.Something)
.WithMany()
.HasForeignKey(a => a.SomethingId);

Both mappings will create exactly the same database schema with a non-nullable foreign key SomethingId and a referential constraint between the two related tables.
The first mapping with MapKey is used when you don't want to have the foreign key as a property in your model class. The type of association in this case is called Independent Association. You would apply the second mapping with HasForeignKey when the foreign key is a property in the model. This type is called Foreign Key Association.
In many scenarios it is easier to work with Foreign Key Associations, but many people consider it as less clean to have a relational artifact (a foreign key) in the object world and prefer Independent Associations therefore.
Here are some references about the two types of associations and their Pros and Cons:
http://www.ladislavmrnka.com/2011/05/foreign-key-vs-independent-associations-in-ef-4/
What are Independent Associations and Foreign Key Associations?
Code First: Independent associations vs. Foreign key associations?

Related

Override Entity Framework Core convention for primary key in a join table

Consider two models, Book and Author, with a many-to-many relationship between them. By default, EF Core creates a join table with a composition key as its primary key.
I need my own primary key for the join table. I wonder if there is a way to "override" this convention, and define a property that will be a primary key for the join table.
I have tried to solve it with Fluent API, telling EF Core explicitly which table many-to-many relation shall be resolved into, giving it a property Id, and setting it as a primary key
builder
.Entity<Book>()
.HasMany(p => p.Author)
.WithMany(p => p.Book)
.UsingEntity(j => j.ToTable("Book_Author"));
builder.Entity("Book_Author")
.Property(typeof(int), "Id");
builder.Entity("Book_Author").HasKey("Id");
But I got an exception
Cannot use table 'Book_Author' for entity type 'Book_Author (Dictionary<string, object>)' since it is being used for entity type 'BookAuthor (Dictionary<string, object>)' and potentially other entity types, but there is no linking relationship. Add a foreign key to 'Book_Author(Dictionary<string, object>)' on the primary key properties and pointing to the primary key on another entity type mapped to 'Book_Author'

Entity Framework - DB-First - Composite Foreign Keys

I have a database that has a table with a 2-column primary composite key (one int, one bigint.) I have two tables that have a composite foreign key, referencing the first table's composite primary key. The relationships are (as far as I know,) fine and dandy on the database itself.
When generating a DB context via DB-first EF6, these relationships/navigation properties are not represented in the generated models (No virtual members in the two child tables referencing the parent table.)
Since it's db-first, I can't modify the models.
In this case you can put those relationships into the onmodelcreating function in db context. We can put constraint there.

Entity Framework - Join table with composite key and a primary key

I am struggling with the way entity framework handles join tables, specifically because entity framework requires that a join table has a composite key composed of the primary keys on the two related entities I want the hold the relationship for. The problem here is that I need to hold a relationship to the relationship so to speak.
This may be a problem with my database design or equally due to my lack of understanding with EF. It is probably best illustrated through example (see below);
I have three tables each with a primary key:-
Table : DispatchChannel
{ *DispatchChannelID integer }
Table : Format
{ *FormatID integer }
Table : EventType
{ *EventTypeID integer }
The relationship between EventTypes and DispatchChannels is held in EventTypeDispatchChannels (see below) since this only contains a composite key it is not pulled through into our model and entity framework takes care of maintaining the relationship.
Table : EventTypeDispatchChannels
{ EventTypeID integer, DispatchChannelID integer
}
My problem now arises because for each combination of EventTypeID and DispatchChannelID I want to hold a list of available formats, this would be easy if my EventTypeDispatchChannels table had a primary key therefore my other join table would look like this;
Table : EventTypeDispatchChannelFormats
{ EventTypeDispatchChannelID integer, FormatID integer
}
The absence of a primary key on EventTypeDispatchChannels is where I am struggling to make this work, however if I had the key then entity framework no longer sees this as a linked entity.
I'm relatively new to C# so apologies if I have not explained this so well, but any advice would be appreciated.
The moment you want to give an association a more important role than just being a piece of string between two classes, the association becomes a first-class citizen of your domain and it's justified to make it part of the class model. It's also inevitable, but that's secondary.
So you should map EventTypeDispatchChannels to a class. The table could have its own simple primary key besides the two foreign keys. A simle PK is probably easier, so your table Format can do with a simple foreign key to EventTypeDispatchChannels for the one-to-many association.
You will lose the many to many feature to simply address dispatchChannel.Events. In stead you have to do
db.DispatchChannels.Where(d => d.DispatchChannelID == 1)
.SelectMany(d => d.EventTypeDispatchChannels)
.Select(ed => ed.Event)
On the other hand you have gained the possibility to create an association by just creating an EventTypeDispatchChannel and setting its primitive foreign key values. Many-to-many associations with a transparent junction table can only be set by adding objects to a collection (add an Event to dispatchChannel.Events). This means that the collection must be loaded and you need an Event object, which is more expensive in database round trips.

Entity Framework Compound Key (Many-To-Many Relationship with a Payload)

I've got database tables like this:
A person may be a member of many teams. A team may have many members. Each person may have a position (think job title) within the team.
I've tried to set this up with ADO.NET Entity Framework and get errors:
Error 3021: Problem in mapping
fragments starting at line ... Each of
the following columns in table
Membership is mapped to multiple
conceptual side properties:
Membership.PersonId is mapped to
<MembershipPerson.Membership.PersonId,
MembershipPerson.Person.Id>
and
error 3021: Problem in mapping
fragments starting at line ... Each of
the following columns in table
Membership is mapped to multiple
conceptual side properties:
Membership.TeamID is mapped to
<MembershipTeam.Membership.TeamId,
MembershipTeam.Team.Id>
The primary key of my Membership entity is a compound key of two foreign keys. I think that's the problem.
What must I do differently?
This happens if you use independent association on the property which is both part of primary key and foreign key. EFv4 introduced Foreign key associations (the difference is described here) and once you expose foreign key in the entity you must define foreign key association. After defining referential constraints delete mapping of independent association in Mapping details window.

E2L: How do you handle Foreign Keys that participate in multiple relationships?

I have a Database model like this
FlowObject
FlowObjectID (PK)
Description
Active
ProcessObject
FlowObjectID (PK, FK)
HasSubmit
DecisionObject
FlowObjectID (PK, FK)
YesFlowObjectID (FK)
NoFlowObjectID (FK)
YesCaption
NoCaption
When I try and use create my Entity model I get this warning in my project.
Foreign Key constraint 'FK_ProcessObject_FlowObject1' has been omitted from the storage model. Column 'FlowObjectID' of table 'Investigations.Store.ProcessObject' is a Foreign Key participating in multiple relationships. A one-to-one Entity Model will not validate since data inconsistency is possible.
???
Why did it drop my foreign key? Because "A one-to-one Entity Model will not validate since data inconsistency is possible."
So it sounds like it is saying it dropped the FK because of data inconsistency but dropping the FK actually reduces date consistency?
Should I redesign my database? Is there anyway for L2E to handle FK's that participate in multiple relationships? Is it considered bad database design to have FK's that participate in multiple relationships?
What you've described, translated to object-oriented terms, is that a FlowObject contains an optional ProcessObject and an optional DecisionObject. If this is what you actually meant, the database schema is correct.
If you're trying to have ProcessObject and DecisionObject extend FlowObject, inconsistency is possible because both the ProcessObject and DecisionObject rows may exist. To eliminate the inconsistency, the union-subclass modeling technique is appropriate: only ProcessObject and DecisionObject tables exist, each containing all relevant fields, and FlowObject, as an abstract base class, becomes a view consisting of the union of the common base fields between the two tables.
I have just get the same error when trying to refactor this. In EFv1 (.NET 3.5) this cannot be solved. In EFv4 (.NET 4.0) you can change independent association (the only association/relation available in EFv1) to foreign key association and it will work. But FK associations have some other drawbacks so it is not a silver bullet.