首页 文章

EF Core Update无法跟踪实体类型'Ads'的实例

提问于
浏览
0

我尝试为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);
    }

任何帮助,将不胜感激 .

1 回答

  • 2

    您已从上下文中添加了 new 'ing up your own entity, when, you should just get that entity you' ve:

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

    有了这段代码,实体框架就说,“嘿,我已经拥有了一个拥有该密钥的实体(检查你的构造函数,你将一个实体放在同一个Id中),但这个对象;我不知道该怎么做用它(因为它来自外面,已经存在一个密钥)“ .

    您可以将其更改为您在上一个测试中正在执行的操作:

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

相关问题