EF Core Update無法跟踪實體類型“廣告”的實例

entity-framework-core xunit

我嘗試為Asp.net Core DBContext實現XUnit測試,但是我得到了以下錯誤。

消息:System.InvalidOperationException:無法跟踪實體類型“Ads”的實例,因為已經跟踪了具有相同鍵的此類型的另一個實例。添加新實體時,對於大多數鍵類型,如果未設置任何鍵,則將創建唯一的臨時鍵值(即,如果為鍵屬性指定了其類型的默認值)。如果要為新實體顯式設置鍵值,請確保它們不會與現有實體或為其他新實體生成的臨時值發生衝突。附加現有實體時,請確保只有一個具有給定鍵值的實體實例附加到上下文。

這是我目前的代碼:

    public class AdsServiceTest
{
    private readonly DbContextOptions<SensingSiteDbContext> _options;
    private readonly SensingSiteDbContext _context;
    private readonly AdsService _AdsService;
    public AdsServiceTest()
    {
        //initialize db options
        _options = new DbContextOptionsBuilder<SensingSiteDbContext>()
            .UseInMemoryDatabase()
            .Options;
        //get service
        _context = new SensingSiteDbContext(_options);
            //initialize dbcontext
            List<Ads> listAds = new List<Ads>() {
                new Ads(){  Id=1,AdsName="Ads1", Deleted=false},
                new Ads(){  Id=2,AdsName="Ads1", Deleted=false},
                new Ads(){  Id=3,AdsName="Ads1", Deleted=false}
            };
         _context.Advertisements.AddRange(listAds);
            //context.Advertisements
            BaseLib.SSDbContext<Ads, AdsService> ssDbContent = new BaseLib.SSDbContext<Ads, AdsService>(_context);
            _AdsService = ssDbContent.GetService((x, y) => new AdsService(x, y));

    }
    [Theory]
    [InlineData(1)]
    public void FindById(int id)
    {
        Ads adsResult = _AdsService.FindById(id);
        Ads adsTarget = _context.Advertisements.Find(adsResult.Id);
        Assert.True(adsTarget.Equals(adsResult));
    }
    //Failed by error System.InvalidOperationException : The instance of entity type 'Ads' cannot be tracked because another instance of this type with the same key is already being tracked
    [Fact]
    public void Update()
    {
        Ads adsResult = new Ads() { Id = 1, AdsName = "UpdateAds1" };
        _AdsService.UpdateAds(adsResult);
        Ads adsTarget = _context.Advertisements.Find(adsResult.Id);
        Assert.True(adsTarget.Equals(adsResult));
    }
}

查找沒有問題,但更新失敗。實現AdsService以調用SensingSiteDbContext。看來我需要為SensingSiteDbContext使用範圍生命週期。但是,我不知道如何實現它。
我已經更改了ObjectState for Update。

        public virtual void Update(TEntity entity)
    {
        entity.ObjectState = ObjectState.Modified;
        _dbSet.Update(entity);            
        _context.SyncObjectState(entity);
    }

任何幫助,將不勝感激。

一般承認的答案

你是new的自己的實體,什麼時候,你應該從上下文中獲得你已經添加的實體:

Ads adsResult = new Ads() { Id = 1, AdsName = "UpdateAds1" };
_AdsService.UpdateAds(adsResult);

有了這段代碼,實體框架就說,“嘿,我已經擁有了一個擁有該密鑰的實體(檢查你的構造函數,你將一個實體放在同一個Id中),但這個對象;我不知道該怎麼做用它(因為它來自外面,已經存在一個密鑰)“。

您可以將其更改為您在上一個測試中正在執行的操作:

Ads adsResult = _AdsService.FindById(id);
//do your changing here
_AdsService.UpdateAds(adsResult);


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow