EF Core Update The instance of entity type 'Ads' cannot be tracked

entity-framework-core xunit

Question

I try to implement a XUnit Test for Asp.net Core DBContext, But I got below error.

Message: 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. When adding new entities, for most key types a unique temporary key value will be created if no key is set (i.e. if the key property is assigned the default value for its type). If you are explicitly setting key values for new entities, ensure they do not collide with existing entities or temporary values generated for other new entities. When attaching existing entities, ensure that only one entity instance with a given key value is attached to the context.

Here is my current code:

    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));
    }
}

There is no problem for Find, but failed on Update. AdsService is implemented to call SensingSiteDbContext. It seems I need to use scope lifetime for SensingSiteDbContext. But, I do not know how to implement it.
I have changed ObjectState for Update.

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

Any help would be appreciated.

1
1
4/15/2017 6:38:05 AM

Accepted Answer

You are new'ing up your own entity, when, you should just get that entity you've already added from the context:

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

With this code, Entity Framework is saying, "Hey, I already have an entity with that key (check your constructor, you're putting an entity in with that same Id), but this object; I don't know what to do with it (because it came from outside with a key that already exists)".

You can change it to exactly what you're doing in the previous test:

Ads adsResult = _AdsService.FindById(id);
//do your changing here
_AdsService.UpdateAds(adsResult);
5
4/13/2017 4:44:10 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow