直接从父实体删除实体时,不同的行为

发布于 2025-02-07 16:28:16 字数 3056 浏览 2 评论 0原文

我正在使用EF核心,我想跟踪实体的删除。现在,当当时使用ChangEtracking删除任何实体时,我会记录该实体,也需要记录IT父实体。

在这种情况下,我以简单的例子为例。在这家公司和部门中,有一对一的关系。

using Microsoft.EntityFrameworkCore;

public class SimpleDbContext 
    : DbContext
{
    public DbSet<Company> Companies { get; set; }
    public DbSet<Department> Departments { get; set; }  

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Company>().HasMany(cc => cc.Departments).WithOne(cc => cc.Company);            
        base.OnModelCreating(modelBuilder);
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=sampletracking;Integrated Security=SSPI");
        base.OnConfiguring(optionsBuilder);
    }

    public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
    {
        foreach(var item in this.ChangeTracker.Entries())
        {
            if(item.State == EntityState.Deleted)
            {
                foreach(var itemRef in item.References)
                {
                    if (!itemRef.IsLoaded)
                        itemRef.Load();
                }
            }
        }

        return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
    }
}

恩典

public class Company
{
    public int Id { get; set; }
    public string CompanyName { get; set; }
    public List<Department> Departments { get; set; }
}

public class Department
{
    public int Id { get; set; }
    public string DepartmentName { get; set; }
    public Company Company { get; set; }
}

准备记录。

using (SimpleDbContext simpleDbContext = new SimpleDbContext())
{
    Company company = new Company();
    company.CompanyName = "Company-1";
    company.Departments = new List<Department>();
    company.Departments.Add(new Department() { DepartmentName = "Department-1" });
    company.Departments.Add(new Department() { DepartmentName = "Department-2" });
    simpleDbContext.Add(company);
    await simpleDbContext.SaveChangesAsync();
}

方案1:删除儿童实体直接。

using (SimpleDbContext simpleDbContext = new SimpleDbContext())
{
    var department = simpleDbContext.Departments.Where(cc => cc.Id == 1).FirstOrDefault();
    simpleDbContext.Remove(department);
    await simpleDbContext.SaveChangesAsync();
}

在这种情况下,当SaveChange调用时,更改跟踪器检测删除及其加载引用(SO parent实体)时,然后成功加载。

方案2:

using (SimpleDbContext simpleDbContext = new SimpleDbContext())
{
    var company = simpleDbContext.Companies
        .Include(cc => cc.Departments)
        .Where(cc => cc.Id == 1).FirstOrDefault();

    company.Departments.RemoveAll(cc => cc.Id == 2);
    
    await simpleDbContext.SaveChangesAsync();
}

正在检测到此方案实体删除中删除的情况下,但是当它尝试加载参考时,它始终是null。

为什么如果相同的实体从同一集合中删除它的行为不同?

I am using EF core and I want to track deletion of entity. Now when any entity get deleted at that time using ChangeTracking I record that entity and also it is required to record it parent entity.

In this scenario I have took simple example. In this Company and Department has one to many relation.

using Microsoft.EntityFrameworkCore;

public class SimpleDbContext 
    : DbContext
{
    public DbSet<Company> Companies { get; set; }
    public DbSet<Department> Departments { get; set; }  

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Company>().HasMany(cc => cc.Departments).WithOne(cc => cc.Company);            
        base.OnModelCreating(modelBuilder);
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=sampletracking;Integrated Security=SSPI");
        base.OnConfiguring(optionsBuilder);
    }

    public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
    {
        foreach(var item in this.ChangeTracker.Entries())
        {
            if(item.State == EntityState.Deleted)
            {
                foreach(var itemRef in item.References)
                {
                    if (!itemRef.IsLoaded)
                        itemRef.Load();
                }
            }
        }

        return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
    }
}

Entties

public class Company
{
    public int Id { get; set; }
    public string CompanyName { get; set; }
    public List<Department> Departments { get; set; }
}

public class Department
{
    public int Id { get; set; }
    public string DepartmentName { get; set; }
    public Company Company { get; set; }
}

Prepare record.

using (SimpleDbContext simpleDbContext = new SimpleDbContext())
{
    Company company = new Company();
    company.CompanyName = "Company-1";
    company.Departments = new List<Department>();
    company.Departments.Add(new Department() { DepartmentName = "Department-1" });
    company.Departments.Add(new Department() { DepartmentName = "Department-2" });
    simpleDbContext.Add(company);
    await simpleDbContext.SaveChangesAsync();
}

Scenario 1 : Delete Child entity direct.

using (SimpleDbContext simpleDbContext = new SimpleDbContext())
{
    var department = simpleDbContext.Departments.Where(cc => cc.Id == 1).FirstOrDefault();
    simpleDbContext.Remove(department);
    await simpleDbContext.SaveChangesAsync();
}

In this scenario when savechange called, Change tracker detect the delete and when It load references ( so parent entity) then it successfully load.

Scenario 2: Delete from Parent

using (SimpleDbContext simpleDbContext = new SimpleDbContext())
{
    var company = simpleDbContext.Companies
        .Include(cc => cc.Departments)
        .Where(cc => cc.Id == 1).FirstOrDefault();

    company.Departments.RemoveAll(cc => cc.Id == 2);
    
    await simpleDbContext.SaveChangesAsync();
}

In this scenario entity delete is being detected but when it try to load reference, it is always null.

Why if same entity delete from same collection it behave differently ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文