Reputation: 125
The relationship of entity A,B is one-to-many, (A has many Bs, B must belong to A).
I disabled lazy loading
and load A, B like this:
dbContext.As.Load();
//**particaly load B**
dbContext.Bs.Where(predicateX).Load();
When I use
dbContext.As.Remove(someA)
To delete A, I encounter the following error message
The relationship could not be changed because one or more of the foreign-key properties is non-nullable
Instead, if I use:
//remove all B in someA
foreach(B b in someA.Bs.ToList())
{
dbContext.Bs.Remove(b);
}
dbContext.As.Remove(someA)
everything is ok.
Is there a better way to do this?
Edit
i am using Database First and add foreign key constraint of B (on delete cascade) at the database side.
i think "the foreign key constraint" is just equal to the code "OnModelCreating". but the code "dbContext.As.Remove(someA)" doesn't work as expected.
things get worse when there is A-B-C cascade one to many relation.in order to delete someA,you need to do like this
foreach(B b in someA.Bs.ToList())
{
foreach(C c in b.Cs.ToList())
{
dbContext.Cs.Remove(c);
}
dbContext.Bs.Remove(b);
}
dbContext.As.Remove(someA);
Solved:
i use database first(sqlite) and add foreign key constraint at database side.
use vs2012 to create edmx from sqlite database file,
vs2012 failed to set the "on delete cascade" property of the relationship.
after manual set the property,single call to "dbContext.As.Remove(someA)" work as expected!
Upvotes: 6
Views: 9079
Reputation: 7140
Sadly, there is (currently) no batch support in Entity Framework, so you're stuck foreach
-ing through multiple properties. You might want to look at the EntityFramework.Extended project, which adds various batch operations to tidy up code like this (as well as improving performance).
If you're sure you'll always want to delete the related B's when an A is deleted, then configure this relationship to use "on delete cascade" behaviour. What that means is that when a parent A is deleted, all of its child B's are automatically deleted as well. How to do that depends on how you've created the database. If you're using Code First, it'll be something like this:
public class MyContext : DbContext
{
public DbSet<A> As { get; set; }
public DbSet<B> Bs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<A>()
.HasMany(a => a.Bs)
.WithRequired(b => b.A)
.WillCascadeOnDelete();
}
}
Upvotes: 8