将更改保存到具有子项的 EF

本文关键字:EF 保存 | 更新日期: 2023-09-27 18:31:22

我有构建报告系统,用户可以在其中选择数据并显示为报告。报表保存在三个表(拆分实体)中。但是当我尝试编辑报告并再次保存时,出现以下错误:

一个实体对象不能被多个 IEntityChangeTracker 实例引用

我的实体:

public class Report
{
    [Key]
    public int ReportId { get; set; }
    public string Title { get; set; }
    public int? DateRange { get; set; }
    public int Layout { get; set; }
    public DateTime? DateFrom { get; set; }
    public DateTime? DateTo { get; set; }
    public int OwnerId { get; set; }
    public DateTime DateCreated { get; set; }
    public bool Active { get; set; } 
    public virtual List<ReportCharts> ReportCharts { get; set; }
    public virtual List<ReportElements> ReportElements { get; set; }
}

我的 EF 存储库:

//Save Report to Database 
    public void Save(Report report)
    {
        assignSettingsToEntity(report);
        assignElementsToEntity(report);
        assignChartsToEntity(report);
        int found = Reports
            .Select(r => r.ReportId)
            .Where(id => id == report.ReportId)
            .SingleOrDefault();
        if (found == 0)
        {
            context.Reports.Add(report);
        }
        else
        {
            context.Entry(report).State = EntityState.Modified; // Here I get error 
        }
        context.SaveChanges();     
    }

我的数据库文本

class EFDbContext : DbContext
{
    //Get Lines data from Lines table
    public DbSet<Line> Lines { get; set; }
    //Get Shifts data from Shifts table
    public DbSet<Shift> Shifts { get; set; }
    //Get list of Charts from Charts table
    public DbSet<Graph> Graphs { get; set; }
    //Get Reports data from Reports table
    public DbSet<Report> Reports { get; set; }
    // Report entity mapping
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Report>().Property(t => t.ReportId).HasColumnName("ReportId");
        modelBuilder.Entity<Report>().Property(t => t.Title).HasColumnName("Title");
        modelBuilder.Entity<Report>().Property(t => t.DateRange).HasColumnName("DateRange");
        modelBuilder.Entity<Report>().Property(t => t.Layout).HasColumnName("Layout");
        modelBuilder.Entity<Report>().Property(t => t.DateFrom).HasColumnName("DateFrom");
        modelBuilder.Entity<Report>().Property(t => t.DateTo).HasColumnName("DateTo");
        modelBuilder.Entity<Report>().Property(t => t.OwnerId).HasColumnName("OwnerId");
        modelBuilder.Entity<Report>().Property(t => t.DateCreated).HasColumnName("DateCreated");
        modelBuilder.Entity<Report>().Property(t => t.Active).HasColumnName("Active");
        modelBuilder.Entity<Report>().HasMany(t => t.ReportElements).WithRequired().HasForeignKey(c => c.ReportId).WillCascadeOnDelete(true);
        modelBuilder.Entity<Report>().HasMany(t => t.ReportCharts).WithRequired().HasForeignKey(p => p.ReportId).WillCascadeOnDelete(true);
        modelBuilder.Entity<ReportElements>().Property(c => c.ElementName).HasColumnName("ElementName");
        modelBuilder.Entity<ReportElements>().HasKey(c => new { c.ReportId, c.ElementName, c.Active });
        modelBuilder.Entity<ReportCharts>().Property(p => p.ChartId).HasColumnName("ChartId");
        modelBuilder.Entity<ReportCharts>().HasKey(c => new { c.ReportId, c.ChartId, c.Active });
    }
}

感谢您的任何帮助。

将更改保存到具有子项的 EF

实体框架将每个实体附加到一个上下文,并且所有更改只能在它附加到它的上下文上执行,您可能正在使用多个上下文。应分离并附加从不同上下文获取的实体。

否则,最佳做法是不要使用多个上下文实例,而是在整个更改过程中仅保留一个上下文。

听起来对象已附加到另一个上下文而不是分离。

   //Save Report to Database 
    public void Save(Report report)
    {
      using(EFDbContext context=new EFDbContext ())
      {
        assignSettingsToEntity(report);
        assignElementsToEntity(report);
        assignChartsToEntity(report);
        int found = context.Reports
            .Select(r => r.ReportId)
            .Where(id => id == report.ReportId)
            .SingleOrDefault();
        // Insert Flow
        if (found == 0)
        {
            context.Reports.Add(report);
        }
        // Update flow
        else
        {
            context.Reports.Attach(report);
            context.Entry(report).State = EntityState.Modified; 
        }
        context.SaveChanges(); 
      }         
    }