How to update FK to null when deleting optional related entity

后端 未结 1 384
说谎
说谎 2020-12-10 04:15

I\'m reasonably new to EF, and struggling a little to facilitate deleting my objects. My two objects and associated DbContext look as follows:

public class C         


        
相关标签:
1条回答
  • 2020-12-10 04:36

    Although SQL Server supports it, as you have guessed, EF is not able to set a cascading rule to nullify the FK when the related object is deleted: Entity Framework: Set Delete Rule with CodeFirst

    So you need to include in the context the related objects, so that when you delete the Person the related vehicles are updated with a null PersonId. You don't need to include a list for this. You can make the DbContext aware of the related entities like this:

    ctx.Vehicles.Where(v => v.PersonId == personId).Load();
    

    Then, if you call delete, it will work as expected.

    This is a sample DbContext, configured with fluent API, which works as expected:

    public class SampleDbContext: DbContext
    {
        public SampleDbContext()
            : base("name=CascadeOnDelete")
        {
    
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Vehicle>()
                .HasOptional(v => v.Person)
                .WithMany()
                .HasForeignKey(v => v.PersonId);
                //.WillCascadeOnDelete();
            base.OnModelCreating(modelBuilder);
        }
    
        public DbSet<Person> Persons {get;set;}
        public DbSet<Vehicle> Vehicles {get;set;}
    }
    
    public class Person
    {
        public int PersonId {get;set;}
        public string Name {get;set;}
    }
    
    public class Vehicle
    {
        public int VehicleId {get;set;}
        public string Model { get; set; }
        public int? PersonId { get; set; }
        public virtual Person Person {get;set;}
    } 
    

    And this console app shows the expected behavior:

    class Program
    {
        static void Main(string[] args)
        {
            using (var ctx = new SampleDbContext())
            {
                Console.WriteLine("Creating John McFlanagan and their 2 vehicles");
                var person = new Person {Name = "John McFlanagan"};
                var vehicle1 = new Vehicle { Person = person, Model = "Vauxhall Astra" };
                var vehicle2 = new Vehicle { Person = person, Model = "Ford Capri" };
    
                ctx.Vehicles.AddRange(new[] {vehicle1, vehicle2});
                ctx.SaveChanges();
            }
    
            using (var ctx = new SampleDbContext())
            {
                var person = ctx.Persons.First();
                // Loading related vehicles in the context
                ctx.Vehicles.Where(v => v.PersonId == person.PersonId).Load();
                Console.WriteLine("Deleting the person, and nullifying vehicles PersonId");
                ctx.Persons.Remove(person);
                ctx.SaveChanges();
            }
    
        }
    }
    

    In (EF7) EF Core it's possible to set the behaviour

    Thanks to @Dabblernl comment: http://blogs.msdn.com/b/adonet/archive/2015/10/15/ef7-beta-8-available.aspx#comments

    Diego B Vega [MSFT] 17 Oct 2015 9:21 PM # @DabblerNL yes, the functionality is already implemented in current nightly builds. You will have to explicitly specify it in the model using .OnDelete(DeleteBehavior.SetNull).

    The previous link is dead. You can see the description of this model property here: http://www.learnentityframeworkcore.com/conventions/one-to-many-relationship

    0 讨论(0)
提交回复
热议问题