简体   繁体   English

无法跟踪实体类型“ Article”的实例,因为已经跟踪了另一个具有相同键值的{'Id'}实例

[英]The instance of entity type 'Article' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked

I am writing unit tests for my generic repository, but when I run my update method it fails. 我正在为通用存储库编写单元测试,但是当我运行更新方法时,它将失败。

My test method looks like this: 我的测试方法如下:

    private async Task TestUpdate()
    {
        var compare = testArticles[0];
        var article = await testInstance.SelectSingleAsync(new AdHocSpecification<Article>(x => x.Id == compare.Id), x => x.ArticleImages).ConfigureAwait(false);

        Compare(article, compare);

        article.Brand = "Air-Bam";
        article.DescriptionDutch = "Ter aldus dus juist wij zware. Hadden met karank afzien dat oog dus invoer oorlog. Oogenblik zoo volledige zin mag stoompomp schatkist. Per had met tot sinds batoe zelfs. Dit opgericht producten ontrukten schatkist het. Verkoopen ons die omgewoeld gebergten honderden dus het.";
        article.DescriptionFrench = "Comme verts mes comme ces nul fut. Et ah te avons rente rouge je. Il ainsi il cause oh croix utile or. Jeunesse poitrine en epanouir la reparler la. Jet noble force par arret ras voila votre peu. Les ete appareil supplice vit epandent. Collines dissiper cavalier octogone la magasins ca.";
        article.Discount = 80;
        article.IsDeleted = true;
        article.Price = 1000;
        article.Title = "Air Tone";

        await testInstance.UpdateAsync(article).ConfigureAwait(false);

        Assert.AreNotEqual(article.Brand, compare.Brand);
        Assert.IsNotNull(article.ArticleImages);
        Assert.IsFalse(article.ArticleImages.ToList().SequenceEqual(compare.ArticleImages.ToList()));
        Assert.AreNotEqual(article.DescriptionDutch, compare.DescriptionDutch);
        Assert.AreNotEqual(article.DescriptionFrench, compare.DescriptionFrench);
        Assert.AreNotEqual(article.Discount, compare.Discount);
        Assert.AreNotEqual(article.IsDeleted, compare.IsDeleted);
        Assert.AreNotEqual(article.Price, compare.Price);
        Assert.AreNotEqual(article.Title, compare.Title);
    }

The SelectSingleAsync and UpdateAsync methods look like the following: SelectSingleAsync和UpdateAsync方法如下所示:

    public virtual Task<TObj> SelectSingleAsync(Specification<TObj> spec, params Expression<Func<TObj, object>>[] includes)
    {
        return _context.Set<TObj>().Includes(includes).Where(spec.ToExpression()).AsNoTracking().FirstOrDefaultAsync();
    }

    public virtual async Task UpdateAsync(TObj obj)
    {
        _context.Set<TObj>().Update(obj);
        await _context.SaveChangesAsync().ConfigureAwait(false);
    }

When the Update method gets executed, an exception gets thrown: 执行Update方法时,将引发异常:

System.InvalidOperationException: The instance of entity type 'Article' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. System.InvalidOperationException:无法跟踪实体类型“ Article”的实例,因为已经跟踪了另一个具有相同“ {'Id'}”键值的实例。 When attaching existing entities, ensure that only one entity instance with a given key value is attached. 附加现有实体时,请确保仅附加一个具有给定键值的实体实例。 Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values. 考虑使用'DbContextOptionsBuilder.EnableSensitiveDataLogging'来查看冲突的键值。

I do not understand why it is saying that it is already being tracked, as I am clearly using AsNoTracking() in my select method. 我不明白为什么要说它已经被跟踪,因为我显然在我的select方法中使用了AsNoTracking() What can I do to fix this? 我该怎么做才能解决此问题?

Edit: The Article class looks like the following 编辑:Article类如下所示

public class Article:Entity<Guid>
{
    public string Title { get; set; }
    public string Brand { get; set; }
    public string DescriptionDutch { get; set; }
    public string DescriptionFrench { get; set; }
    public decimal Price { get; set; }
    public int Discount { get; set; }

    public ICollection<ArticleImage> ArticleImages { get; set; }

    public override bool Equals(object obj)
    {
        if (!(obj is Article article)) return false;
        return article.Title.Equals(Title)
            && article.Id.Equals(Id)
            && article.IsDeleted.Equals(IsDeleted)
            && article.Brand.Equals(Brand)
            && article.DescriptionDutch.Equals(DescriptionDutch)
            && article.DescriptionFrench.Equals(DescriptionFrench)
            && article.Price.Equals(Price)
            && article.Discount.Equals(Discount)
            && article.ArticleImages.SequenceEqual(ArticleImages);
    }
}

public abstract class Entity<TKey> where TKey : struct
{
    [Key] public TKey Id { get; set; }

    public bool IsDeleted { get; set; }
}

My context class looks like this: 我的上下文类如下所示:

public class ApplicationDbContext : IdentityDbContext<User>, IApplicationDbContext
{
    public ApplicationDbContext(DbContextOptions options)
        : base(options)
    {
    }

    public ApplicationDbContext()
    {
    }

    public DbSet<HomePageItem> HomePageItem { get; set; }
    public DbSet<Country> Country { get; set; }
    public DbSet<Address> Address { get; set; }
    public DbSet<Translation> Translation { get; set; }
    public DbSet<Article> Article { get; set; }
    public DbSet<ArticleImage> ArticleImage { get; set; }
}

Edit 2: Example of article that gets inserted: 编辑2:插入的文章示例:

        new Article
        {
            Brand = "Lorem",
            ArticleImages = new List<ArticleImage>{
                new ArticleImage
                {
                    Order = 0,
                    Url = "foo"
                },
                new ArticleImage
                {
                    Order = 1,
                    Url = "bar"
                }
            },
            DescriptionDutch = "Wier heft zien mont gaat zijn al en of. Wel brusch zin worden dienen bladen des vooral oosten. Nam behoeft noemden haalden elk. Stuit spijt enkel vogel oog een vindt geldt. Aangewend bezetting wijselijk arbeiders om is op antwerpen japansche af. Systemen planters vreemden kan hen passeert ons dichtbij dit. Met gevestigd wij financien als behoeften.",
            DescriptionFrench = "Air courtes reciter moi affreux croisee. La xv large en etais roidi ponts terre. Siens homme pic peu jeu glace beaux. Ca ma apres pitie sacre monde et voici. Battirent il echangent la croissent esplanade sortaient du ce. Fanatiques infanterie eux mon etonnement ecouterent imprudente assurances. Bambous fleurir ai arriere tu longues souffle etoffes un.",
            Discount = 10,
            IsDeleted = false,
            Price = 200,
            Title = "Tipfan"
        }

Code that does the insert: 执行插入的代码:

    public virtual async Task InsertAsync(TObj obj)
    {
        _context.Set<TObj>().Add(obj);
        await _context.SaveChangesAsync().ConfigureAwait(false);
    }

When you fetch data from database, and iterate over it, like: 当您从数据库中获取数据并对其进行迭代时,例如:

var dataObject = await dbContext.Table.where(x=>x.UserId == model.UserId).TolistAsync();
foreach(var item in dataObject)
{ 

}

do not create another object, pass the fetched object directly to Delete or use it to update, because DbContext is tracking the objects it has fetched, not the ones you create. 不要创建另一个对象,将获取的对象直接传递给Delete或使用它进行更新,因为DbContext跟踪的是它获取的对象,而不是您创建的对象。 for example: 例如:

//Wrong code //错误代码

var dataObject = await dbContext.Table.where(x=>x.UserId == model.UserId).TolistAsync();
foreach(var item in dataObject)
{ 
   var x=new DataObject()
   {
      x=item.Id
   };
   dbContext.Table.Remove(x);
}

you must pass the originally fetched instance to Remove() method, see: 您必须将原始获取的实例传递给Remove()方法,请参见:

var dataObject = await dbContext.Table.where(x=>x.UserId == model.UserId).TolistAsync();
foreach(var item in dataObject)
{ 
    dbContext.Table.Remove(item);
}

Try to repair your code like this: 尝试像这样修复您的代码:

     public class Article:Entity<Guid>
    {
        public string Title { get; set; }
        public string Brand { get; set; }
        public string DescriptionDutch { get; set; }
        public string DescriptionFrench { get; set; }
        public decimal Price { get; set; }
        public int Discount { get; set; }

        public ICollection<ArticleImage> ArticleImages { get; set; }

//add constructor, and initilize the id        
public Article(){
    this.Id = Guid.NewGuid();
    }

        public override bool Equals(object obj)
        {
            if (!(obj is Article article)) return false;
            return article.Title.Equals(Title)
                && article.Id.Equals(Id)
                && article.IsDeleted.Equals(IsDeleted)
                && article.Brand.Equals(Brand)
                && article.DescriptionDutch.Equals(DescriptionDutch)
                && article.DescriptionFrench.Equals(DescriptionFrench)
                && article.Price.Equals(Price)
                && article.Discount.Equals(Discount)
                && article.ArticleImages.SequenceEqual(ArticleImages);
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法跟踪实体类型“Entity”的实例,因为已跟踪另一个具有与 {'Id'} 相同键值的实例 - The instance of entity type 'Entity' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked 实体类型的实例 <T> 无法跟踪,因为已经跟踪了另一个具有相同的{&#39;Id&#39;}键值的实例 - The instance of entity type <T> cannot be tracked because another instance with the same key value for {'Id'} is already being tracked 无法跟踪实体类型 Model 的实例,因为已跟踪另一个具有相同 {&#39;Id&#39;} 键值的实例 - The instance of entity type Model cannot be tracked because another instance with the same key value for {'Id'} is already being tracked 无法跟踪实体类型“Bus”的实例,因为已经在跟踪具有相同键值 {'Id'} 的另一个实例 - The instance of entity type ‘Bus’ cannot be tracked because another instance with the same key value for {‘Id’} is already being tracked 无法跟踪实体类型“AppUser”的实例,因为已跟踪另一个具有与 {'Id'} 相同键值的实例 - The instance of entity type 'AppUser' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked 无法跟踪实体类型“IdentityUser”的实例,因为已跟踪另一个具有与 {'Id'} 相同键值的实例 - The instance of entity type 'IdentityUser' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked 无法跟踪实体类型“书签”的实例,因为已经在跟踪具有相同键值 {'ID'} 的另一个实例 - The instance of entity type 'Bookmark' cannot be tracked because another instance with the same key value for {'ID'} is already being tracked 无法跟踪实体类型“Item”的实例,因为已跟踪另一个具有与 {'Id'} 相同键值的实例 - The instance of entity type 'Item' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked 无法跟踪实体类型的实例,因为已跟踪另一个具有与 {'Id'} 相同键值对的实例 - The instance of the entity type cannot be tracked because another instance with the same key value pair for{'Id'} is already being tracked 无法跟踪实体类型“用户”的实例,因为已经在跟踪另一个具有相同键值的“Id”实例 - The instance of entity type 'User' cannot be tracked because another instance with the same key value for 'Id' is already being tracked
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM