Configure One-to-Many Relationship in Entity Framework 6
If you have bidirectional relationships, Entity Framework will keep them in sync If no foreign key property is defined in your classes, Code First will assume the. I've spent last few days working on code generation for cascade delete relationships, composite keys, foreign keys, data annotations, Code. The ForeignKey attribute is used to configure a foreign key in the relationship between two entities in EF 6 and EF Core. Entity Framework code-first example .
You can use data annotations. And finally, you can configure relationships by convention. Data Annotations I can also set a property to be required with data annotations. Using the same example, I can set EquipmentType to be required by including an annotation when declaring it in the model class: By Convention So what is configuration by convention? When you follow some simple rules on property types and names, Entity Framework will auto-configure many of the software and database features.
Configuring Relationships in Entity Framework Configuring scalar non-relational properties is quite straightforward, but when it comes to entity relationships, it can be more tricky to decide which approach is best for configuring them.
By default, when I delete a Student, I will get a referential integrity error: Note, that when working with 1-to-1 or 1-to When foreign key columns are not included in the model, the association information is managed as an independent object.
Relationships are tracked through object references instead of foreign key properties. This type of association is called an independent association. The most common way to modify an independent association is to modify the navigation properties that are generated for each entity that participates in the association. You can choose to use one or both types of associations in your model. However, if you have a pure many-to-many relationship that is connected by a join table that contains only foreign keys, the EF will use an independent association to manage such many-to-many relationship.
The following image shows a conceptual model that was created with the Entity Framework Designer. The model contains two entities that participate in one-to-many relationship. Both entities have navigation properties. Course is the depend entity and has the DepartmentID foreign key property defined.
The following code snippet shows the same model that was created with Code First. For information on setting up relationships in your model, see the following pages. Creating and modifying relationships In a foreign key association, when you change the relationship, the state of a dependent object with an EntityState. Unchanged state changes to EntityState. In an independent relationship, changing the relationship does not update the state of the dependent object. The following examples show how to use the foreign key properties and navigation properties to associate the related objects.
With foreign key associations, you can use either method to change, create, or modify relationships. With independent associations, you cannot use the foreign key property.
The ForeignKey Attribute | Learn Entity Framework Core
By assigning a new value to a foreign key property, as in the following example. This class has both a navigation property Accommodation and a foreign key property AccommodationId for the same relationship. Code First convention was not able to infer that AccommodationId is meant to be the foreign key.
It simply found no properties that matched any of the three patterns that Code First convention uses to detect foreign key properties, and therefore created its own foreign key. Fixing foreign key with Data Annotations You can configure foreign key properties using the ForeignKey annotation to clarify your intention to Code First. Adding ForeignKey to the AccommodationId, along with information telling it which navigation property represents the relationship it is a foreign key for, will fix the problem: To specify the relationship, begin with the InternetSpecial entity.
Identifying the relationship to be configured modelBuilder.
InternetSpecials What we want to change, however, is something about the foreign key that is also involved with this relationship. Code First expects the foreign key property to be named LodgingId or one of the other conventional names. So we need to tell it which property truly is the foreign key—AccommodationId.
Specifying a foreign key property when it has an unconventional name modelBuilder. Working with Inverse Navigation Properties So far Code First has always been able to work out that the two navigation properties we have defined on each end of a relationship are in fact different ends of the same relationship.
It has been able to do this because there has only ever been one possible match. For example, Lodging only contains a single property that refers to Destination Lodging. Destination ; likewise, Destination only contains a single property that references Lodging Destination. You will need to provide some additional configuration.
For example, what if you kept track of two contacts for each lodging? Go ahead and add these properties to the Lodging class: This will allow you to navigate from a Person to the Lodging instances that they are primary and secondary contact for. Add the following two properties to the Person class: Because there are two sets of navigation properties, Code First is unable to work out how they match up.
Too many foreign keys in the Lodgings table Code First convention can identify bidirectional relationships, but not when there are multiple bidirectional relationships between two entities. You can place the annotations on either end of the relationship or both ends if you want.
The InverseProperty Data Annotation needs the name of the corresponding navigation property in the related class as its parameter. PrimaryContact on one end and Person. PrimaryContactFor on the other. Configuring multiple relationships fluently modelBuilder. SecondaryContactFor ; Working with Cascade Delete Cascade delete allows dependent data to be automatically deleted when the principal record is deleted.
If you delete a Destination, for example, the related Lodgings will also be deleted automatically. Entity Framework supports cascade delete behavior for in-memory data as well as in the database. As discussed in Chapter 19 of the second edition of Programming Entity Frameworkit is recommended that you implement cascade delete on entities in the model if their mapped database objects also have cascade delete defined.
By convention, Code First switches on cascade delete for required relationships. When a cascade delete is defined, Code First will also configure a cascade delete in the database that it creates. Earlier in this chapter we looked at making the Lodging to Destination relationship required. In other words, a Lodging cannot exist without a Destination. Therefore, if a Destination is deleted, any related Lodgings that are in memory and being change-tracked by the context will also be deleted.
When SaveChanges is called, the database will delete any related rows that remain in the Lodgings table, using its cascade delete behavior. Looking at the database, you can see that Code First carried through the cascade delete and set up a constraint on the relationship in the database. The code uses a context to insert a new Destination with a couple of Lodgings. It then saves these Lodgings to the database and records the primary of the new Destination. In a separate context, the code then retrieves the Destination and its related Lodgings, and then uses the Remove method to mark the Destination instance as Deleted.
Configuring Entity Relationships with Entity Framework
WriteLine to inspect the state of one of the related Lodging instances that are in memory. The Entry method gives us access to the information that EF has about the state of a given object.
Next, the call to SaveChanges persists the deletions to the database. Add destination ; context. Remove destination ; Console. WriteLine "State of one Lodging: It is Deleted also even though we did not explicitly remove any of the Lodgings.
The first two are to delete the related Lodging instances that were in memory and the third to delete the Destination. Remove destination ; context. The database cascade delete will delete the related lodgings in response. When querying for the Lodgings at the end, since the database deleted the lodgings, the query will return no results and the lodgings variable will be an empty list. Turning On or Off Client-Side Cascade Delete with Fluent Configurations You might be working with an existing database that does not use cascade delete or you may have a policy of being explicit about data removal and not letting it happen automatically in the database.
But you may want a required relationship in your classes without leveraging cascade delete.
For the scenarios where you want a required relationship but no cascade delete, you can explicitly override the convention and configure cascade delete behavior with the Fluent API. This is not supported with Data Annotations. Keep in mind that if you set the model up this way, your application code will be responsible for deleting or reassigning dependent data when necessary.
Working within the LodgingConfiguration class, the relationship is defined as: WillCascadeOnDelete—one of the configurations you can add to a fluently described relationship Now you can set WillCascadeOnDelete to false for this relationship: WillCascadeOnDelete false Warning If you add the above code to your project, remove it again before continuing with the rest of this chapter.
This will also mean that the database schema that Code First generates will not include the cascade delete.