我正在嘗試通過讀取物體(使用 Entity Framework 6)、將新屬性映射到該物體(使用 AutoMapper)然后呼叫context.SaveChanges().
我遇到的問題圍繞著我的物體中的導航屬性。似乎在映射期間,正在創建一個新物件并將其分配給導航屬性,而不是簡單地更新現有物件的屬性。
這是我的域物件:
public class ParagraphComponent : IReportComponent
{
public Guid ComponentId { get; set; }
public float LineHeight { get; set; }
public ReportTextList TextItems { get; set; } = new ReportTextList();
}
public class ReportTextList : IList<ReportText>
{
private readonly IList<ReportText> _list = new List<ReportText>();
public int Count => _list.Count;
public bool IsReadOnly => _list.IsReadOnly;
// Overrides for IList...
public void Add(ReportText item)
{
_list.Add(item);
}
// ...Remove(), Insert() etc.
}
public class ReportText
{
public Guid Id { get; set; }
public string Content { get; set; } = "";
}
物體框架物體:
public partial class ParagraphComponentEntity
{
public System.Guid ComponentId { get; set; } // ComponentId (Primary key)
public double LineHeight { get; set; } // LineHeight
public virtual System.Collections.Generic.ICollection<ReportTextEntity> ReportTexts { get; set; }
}
public partial class ReportTextEntity
{
public System.Guid Id { get; set; } // Id (Primary key)
public string Content { get; set; } // Content
}
我在做什么:我正在ParagraphComponent從 API 端點獲取資料以執行更新。我基于加載現有組件ParagraphComponent.Id,然后將新屬性映射到現有物體。
這作業正常:
public async Task<bool> EditComponent(IReportComponent editedComponent)
{
var currentParagraphComponentEntity = await Context
.ParagraphComponents
.FirstOrDefaultAsync(x => x.ComponentId == editedComponent.ComponentId)
.ConfigureAwait(false);
Mapper.Map(editedComponent as ParagraphComponent, currentParagraphComponentEntity);
Context.SaveChanges();
}
我可以在除錯中看到屬性映射正確,但是在SaveChanges()呼叫時出現以下錯誤:
違反主鍵約束“PK_ReportText”。無法在物件“dbo.ReportText”中插入重復鍵
似乎映射程序正在為ParagraphComponentEntity.ReportTexts屬性分配一個新物件,因此物體框架將其視為“添加”而不是“更新”,因此它嘗試向該表添加一個新行,該行由于執行主鍵而出錯Id 是唯一的。
我的 AutoMapper 配置:
CreateMap<ParagraphComponent, ParagraphComponentEntity>()
.ForMember(dest => dest.LineHeight, src => src.MapFrom(s => s.LineHeight))
.ForMember(dest => dest.ReportTexts, src => src.MapFrom(s => s.TextItems))
.ForMember(dest => dest.ComponentId, src => src.MapFrom(s => s.ComponentId))
.ForAllOtherMembers(src => src.Ignore());
如果 AutoMapper 為ReportTexts導航屬性創建新實體是問題所在,我該如何解決?
uj5u.com熱心網友回復:
似乎您從資料庫中獲取資料的代碼只是在獲取主要資源ParagraphComponent。默認情況下,集合ReportTexts不會被提取到 EF 背景關系中,因為據我所知 EF 是延遲加載 - 例如,您需要急切地加載參考.Include(..)的物體。
如果我是對的 - 那么在將您的資料映射到物體ReportTexts集合之前是空的,并且您的映射代碼實際上是在該集合中創建新專案。這些物體來自 EF 背景關系之外(閱讀有關 EF ChangeTracking 的資訊),因此“它”認為這些是需要插入資料庫的新物體。這些物件顯然已經包含Id帶有現有鍵的集合 - 所以這就是你遇到沖突的地方。
我認為如果您渴望加載您的物體,那么 EF 應該改為執行更新
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/526547.html
標籤:C#实体框架实体框架 6自动映射器
