Jak usunąć potomne od jednego do wielu powiązanych rekordów w bazie danych EF code first?
Cóż, mam jeden do wielu pokrewny model:
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public string ChildName { get; set; }
}
Chcę wyczyścić Parent.Children
i usunąć powiązane elementy podrzędne z bazy danych. Już próbowałem:
Klasa kontekstu bazy danych:
modelBuilder.Entity<Parent>()
.HasMany(p => p.Children)
.WithOptional()
.WillCascadeOnDelete(true);
To działa dobrze, ale nadal mam zbędne rekordy w bazie danych z polami Parent_Id = null
kiedy robię
parent.Children.Clear();
repository.InsertOrUpdate(parent);
W mojej klasie repozytorium. Również to samo zachowanie jest wtedy, gdy robię:
modelBuilder.Entity<Parent>()
.HasMany(pr => pr.Children)
.WithOptional(ri => ri.Parent)
.WillCascadeOnDelete(true);
Z dodatkową Parent
właściwością w Child
Klasa
public class Child
{
...
public Parent Parent { get; set; }
...
}
Or when I do
modelBuilder.Entity<Child>()
.HasOptional(p => p.Parent)
.WithMany(p => p.Children)
.HasForeignKey(p => p.Parent_Id)
.WillCascadeOnDelete(true);
Z dodatkową właściwością Parent_Id w klasie Child
public class Child
{
...
public int Parent_Id { get; set; }
...
}
Więc, jak mogę skonfigurować kasowanie kaskadowe poprawnie? Albo jak mam usunąć te dziecięce byty? Zakładam, że to przypadkowe zadanie, ale coś mi umyka.
5 answers
Kaskadowe usuwanie nie ma tutaj żadnego efektu, ponieważ nie usuwa się parent
, ale po prostu wywołuje InsertOrUpdate
. Poprawną procedurą jest usuwanie dzieci jeden po drugim, jak na przykład:
using (var context = new MyContext())
{
var parent = context.Parents.Include(p => p.Children)
.SingleOrDefault(p => p.Id == parentId);
foreach (var child in parent.Children.ToList())
context.Children.Remove(child);
context.SaveChanges();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-20 18:28:45
W EF6 szybszym sposobem wykonania operacji jest..
context.Children.RemoveRange(parent.Children)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-29 23:53:11
Spróbuj zmienić na
public virtual ICollection<Child> Children { get; set; }
Ponieważ wirtualny jest potrzebny do leniwego ładowania. jak wyjaśniono tutaj
Myślę, że twój rodzic.Dzieci.Wyczyść nie działa, ponieważ dzieci nie zostały załadowaneWarning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:20
Jeśli twój obiekt odnosi się do siebie, możesz usunąć zarówno wiele do wielu, jak i jedno do wielu dzieci za pomocą poniższej metody. Tylko pamiętaj, żeby zadzwonić do db.SaveChanges ():)
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Object obj = this.db.Objects.Find(id);
this.DeleteObjectAndChildren(obj);
this.db.Objects.Remove(obj);
this.db.SaveChanges();
return this.Json(new { success = true });
}
/// <summary>
/// This deletes an object and all children, but does not commit changes to the db.
/// - MH @ 2016/08/15 14:42
/// </summary>
/// <param name="parent">
/// The object.
/// </param>
private void DeleteObjectAndChildren(Object parent)
{
// Deletes One-to-Many Children
if (parent.Things != null && parent.Things.Count > 0)
{
this.db.Things.RemoveRange(parent.Things);
}
// Deletes Self Referenced Children
if (parent.Children != null && parent.Children.Count > 0)
{
foreach (var child in parent.Children)
{
this.DeleteObjectAndChildren(child);
}
this.db.Objects.RemoveRange(parent.Children);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-15 13:54:36
To się nazywa "kasowanie sierot".
Czy EF może automatycznie usuwać osierocone dane, jeśli rodzic nie zostanie usunięty?
Nie wiem jak to działa w EF6 ale w EF Core działa dobrze https://docs.microsoft.com/en-us/ef/core/saving/cascade-delete więc niekoniecznie trzeba usunąć rodzica kaskady do pracy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-05 21:10:58