Entity Framework 7: Identifying relationships

c# ef-fluent-api entity-framework entity-framework-core

Question

In previous versions of EF I can use following code to implement an identifying relationship:

public class Child
{
    [Key, Column(Order = 1)]
    public virtual int Id { get; set; }

    [Key, Column(Order = 2)]
    public virtual int ParentId { get; set; }
    public virtual Parent Parent { get; set; }
}

It's needed to easily remove a child from collection like this:

var parent = _context.Parents.First();
var child = parent.Children.First();

parent.Children.Remove(child);

_context.SaveChanges();

This approach is described in http://www.kianryan.co.uk/2013/03/orphaned-child/ (the method #2).

But in EF7 this code throws exception when migration is creating:

An exception was thrown while executing a resolve operation. See the InnerException for details. ---> Entity type 'Child' has composite primary key defined with data annotations. To set composite primary key, use fluent API.

I also tried to use FluentAPI as described in How to define nested Identifying Relationships Entity Framework code first in following code:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Parent>()
            .HasMany(p => p.Children)
            .WithOne(c => c.Parent);

        modelBuilder.Entity<Child>()
            .HasKey(c => new {c.Id, c.ParentId});

        base.OnModelCreating(modelBuilder);
    }

This approach allow generate a migration successfully, but when I tried to remove a child from Children collection I got following exception:

System.InvalidOperationException: The association between entity types 'Parent' and 'Child' has been severed but the foreign key for this relationship cannot be set to null. If the dependent entity should be deleted, then setup the relationship to use cascade deletes.

But I wouldn't like to use cascade deletes, I would like to use identifying relationship!

Please, help me understand what I do incorrect. Thank you!

1
1
5/23/2017 12:23:47 PM

Accepted Answer

Use cascade on delete instead as this is what it's used for:

modelBuilder.Entity<Parent>()
    .HasMany(p => p.Children)
    .WithOne(c => c.Parent);
    .WillCascadeOnDelete(true);

https://msdn.microsoft.com/en-gb/data/jj591620.aspx

2
3/15/2016 3:00:43 PM

Popular Answer

Just in case someone sees this error, let me tell you how I resolved mine:

When you do an update, on EF you need to first query the database and get the data model, then map the Domain layer model with your changes onto it (basically copying fields onto the data), and finally call the DBContext update method, then save changes.

My problem was that my model (not the data model, the domain model) also had the sub objects on it.

So here's the data layer model (for example):

public class Parent
{
   public int ChildId {get; set; }

   [ForeignKey("ChildId")]
   public virtual Child Child { get; set; }
}

And here's how the domain layer model should be:

public class Parent
    {
        public int ChildId { get; set; }
        //public Child Child { get; set; }  // this caused the error, keep reading if you want to know more.
    }

When I was seeing the error, I had been using Autofac's runtime mapper to map the domain layer model's properties onto the data layer model. However, the child in the domain layer model was null, so it would nullify the data layer, causing the error:

"The association between entity types 'Parent' and 'Child' has been severed but the foreign key for this relationship cannot be set to null. If the dependent entity should be deleted, then setup the relationship to use cascade deletes."


By the way, in the db context class, I have the following relationship defined:

modelBuilder.Entity<Parent>()
   .HasOne(a => a.Child)
   .WithMany()
   .HasForeignKey(p => p.ChildId)
   .OnDelete(DeleteBehavior.Restrict);

It's working.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow