Entity Framework Model first: adding an association without creating foreign key properties? - entity-framework

I'm playing with the Entity Framework model designer, and I've got a question about creating entity associations:
In the "create association" dialog, when I create a 1:many association, it offers this checkbox:
"Add foreign key properties to the [entityname] entity"
I've been checking this box and I get results that are expected and make sense to me: Clicking the navigation property in the diagram highlights the related field in both entities that tie them together.
But, what would it mean not to check this box? I've tried this, and I then see no place in the entity to store a reference to the parent table's primary id. Am I correct that the navigation properties don't store any data in the database? If so, how could this work? Am I, perhaps, expected to manually map the navigation property to an Int32 field on the entity?

Associations represent relationship between entities. In the database (relational model) these relations are modeled by using foreign keys and - in the case of many-to-many - a join table. In the object model relations are typically modeled as references to the related object (in EF they are often referred to as Navigation Properties). The problem arises when you need to create or modify a relationship in the object model - you always need to have a reference of the related object you would like to set. In a pure object model this usually is not a problem but in case of ORM it means that if you don't have the related entity you need to send a query to the database to get the object to be able to set the reference to. However oftentimes - even if you don't have the related entity - you know the Id of the related entity. So, if the foreign key properties were exposed (and handled) in your object model you could create or modify a relationship without having to send additional queries to the database. This is what the checkbox is about. If you check it your entities will have (extraneous from object model perspective) properties mapped to foreign key columns in the database which you can use to manipulate relationships.

Related

Entity Framework Core: how to 'wipe and replace' bridge table?

Imagine we have a many-to-many relationship (e.g. Product and Category where one product can be in many categories and vice versa). They are identified through a composite key (ProductId / CategoryId). How do we update this bridge table in Entity Framework Core when we want to persist the changes to the Product aggregate?
In Entity Framework 6, I'd simply wipe out all related data for that product in the bridge table and then re-populate them. This simplifies life as we don't need to manually synchronize changes (inserts, updates, deletes). Just wipe and replace.
How do we do this in Entity Framework Core? Here's what I tried:
context.ProductCategories.RemoveRange(product.Categories);
context.ProductCategories.AddRange(updatedProductCategories);
This results in an exception due to duplicate composite key:
InvalidOperationException: The instance of entity type 'ProductCategory' cannot be tracked because another instance of this
type with the same key is already being tracked. When adding new
entities, for most key types a unique temporary key value will be
created if no key is set (i.e. if the key property is assigned the
default value for its type). If you are explicitly setting key values
for new entities, ensure they do not collide with existing entities or
temporary values generated for other new entities. When attaching
existing entities, ensure that only one entity instance with a given
key value is attached to the context.
How do we remove a composite key entity from the context so that we can add another one?
The only way I got this to work so far is to synchronize all changes (deletes, updates, inserts), but it would be much simpler to just wipe and replace.

How to find out which property is used as a Foreign Key between two entities in code first approach

I'm using Entity Framework 5, code first approach. As there's no built in support for updating child entities in disconnected scenario, I'm building my own mechanism to do that. At some point I need to get the property of an entity with which it has a Foreign Key relationship with another (principal) entity. I've tried to get access to CSpace through
((IObjectContextAdapter)dbContext).ObjectContext.MetadataWorkspace.GetItems<MyEntity>(System.Data.Entity.Core.Metadata.Edm.DataSpace.CSpace)
but here I got a warning that said there's no implicit conversion between MyEntity and System.Data.Entity.Core.Metadata.Edm.GlobalItem.
I can't look for a property that has Foreign Key attribute because in most of my entities I use EF convention to get foreign keys automatically. So how one would go about finding which property is used for foreign key relationship.
Thanks to #octavioccl's post I was able to do what I want. So I was in the right path to look inside ObjectContext.

MVC4 EF Foreign Key Association causes invalid ModelState

Using EF with MVC4 allows you to specify the inclusion of Foreign Key columns in the model. While this not normally part of OR modeling, it does allow MVC4 to automatically generate views with dropdown lists, for the foreign key relationships, when you generate a controller with the MVC controller with read/write actions and views, using Entity Framework option.
I have hit a problem creating an object in this scenario.
Greatly simplified, the models in question are:
Questionnaire:
QuestionnaireID: PK
CandidateId: FK
Candidate: Associated object
Candidate:
CandidateID: PK
Name: string
The problem I have hit is that on a Create view post-back to create a new Questionnaire ModelState.IsValid is false. On investigation the error listed is The parameter conversion from type 'System.String' to type 'Data.Candidate' failed because no type converter can convert between these types.
ModelState.Keys includes Questionnaire.Candidate as well as Questionnaire.CandidateId (which is valid).
I am sure this is something simple, but would like to hear some solutions. The viewbag only has a set for the drop-down list and the view has an #model of type #model Data.Questionnaire. There are no editor fields bound to Questionnaire.Candidate..
As I have no idea why the built-in EF models do not like the MVC generated scaffolding, for Create postbacks with foreign key columns enabled, I have reverted to what is a more secure solution (still happy to hear why it fails out-of-the-box):
Create individual view models for specific sensitive operations like create
The theory goes that there are a number of problems using EF domain entities as viewmodels including:
They potentially expose too much information or allow additional fields to be posted back
Validation text is an interface concern and should not be part of a the data model (they actually suggest even the viewmodel is not the place for this text, but I digress).
So basically I now have a CreateCandidateQuestionnaireVM class with only the required fields for selecting appropriate values for a new instance.

Do I have to set foreign key properties manually when I change associations?

I'm migrating from Linq-to-SQL to Entity Framework (4.4), using Database First with a DbContext. I'm wondering whether the following behavior is normal:
using (var e = new AgendaEntities()) {
var store = e.Stores.First();
var office = e.Offices.Create();
office.Store = store; // Set association
Console.WriteLine(office.StoreID); // shows Guid.Empty, expected store.ID!
}
In L2S, setting the Store association to an entity would also update the StoreID key. In EF, this doesn't seem to be happening. This is regardless of whether the entities are new or loaded from the context.
When I SaveChanges, it saves correctly and the StoreID is updated to match office.ID, but why does this only happen after the save?
Is there something I'm missing, or am I now supposed to keep foreign keys in sync manually?
Solution Edit:
This is called property fixup, and used to be done automatically by the generated proxies. However, with DbContext this is no longer the case. According to this Connect issue, this is by design.
Hello,
The DbContext template actually doesn't generate classes that will be used as change tracking proxies - just lazy loading proxies (which don't do fix-up). We made this decision because change tracking proxies are complex and have a lot of nuances that can be very confusing to developers.
If you want fix-up to occur before SaveChanges you can call myContext.ChangeTracker.DetectChanges.
~EF Team
An alternative is to call DbContext.Entry(entity), which will sync up the entity. This is described in this article: Relationships and Navigation Properties under "Synchronizing the changes between the FKs and Navigation properties"
No. Entity framework does this for you. Read Relationships and Navigation Properties for more information.
By assigning a new object to a navigation property. The following
code creates a relationship between a course and a department.
If the objects are attached to the context, the course is also
added to the department.Courses collection, and the
corresponding foreign key property on the course object is set to the
key property value of the department.
course.Department = department;
But as you observed, this only happens after you call SaveChanges or one of the other actions mentioned in the "Synchronizing the changes between the FKs and Navigation properties" portion of the document linked above.
If you are using POCO entities without proxies, you must make sure
that the DetectChanges method is called to synchronize the related
objects in the context. Note, that the following APIs automatically
trigger a DetectChanges call.
DbSet.Add
DbSet.Find
DbSet.Remove
DbSet.Local
DbContext.SaveChanges
DbSet.Attach
DbContext.GetValidationErrors
DbContext.Entry
DbChangeTracker.Entries
Executing a LINQ query against a DbSet
If this is not happening at all, my guess is that you haven't properly defined StoreID as the foreign key of the navigation property Store.

DbContext's ChangeTracker problem

I have a codefirst EF-4.1 based program. The user gets a context and can modify some properties. When the user is done, I do a quick
ChangeTracker.Entries().Any(e => e.State != EntityState.Unchanged);
to determine if a SaveChanges() is required or not. If I do a 'SaveChanges()' call, the changes that have made are persisted to the database.
This works for some properties, and doesn't work for others. Specifically it seems to work with simple types (floats), and with collection hierarchies(ObservableCollections).
Am I doing something wrong?
Yes this is a problem. Some relations are not tracked by DbChangeTracker. There is difference between Independent association and Foreign key association. Changes to relation are tracked in case of:
One-to-one relation which is always Foreign key association in EFv4+
One-to-many relation with Foreign key association - you should set up foreign key property
Changes to relation are not tracked in case of:
One-to-many relation with Independent association
Many-to-many relation which is always Independent association
Not tracked for Independent association is not correct naming. These changes are tracked but DbChangeTracker does not expose access to these changes! You must convert DbContext to ObjectContext and use ObjectStateManager to get access to ObjectStateEntries representing independent associations.
In this case the easiest thing is simply call SaveChanges always. It will not execute any DB commands if no data need to be saved.