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
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();
}
}
}
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