Я пишу модульные тесты для моего общего репозитория, но когда я запускаю свой метод обновления, он не работает.
Мой метод тестирования выглядит следующим образом:
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);
}
Методы 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);
}
Когда метод Update выполняется, генерируется исключение:
System.InvalidOperationException: экземпляр типа сущности Article не может быть отслеженпотому что другой экземпляр с таким же значением ключа для {'Id'} уже отслеживается.При подключении существующих объектов убедитесь, что подключен только один экземпляр объекта с данным значением ключа.Подумайте об использовании DbContextOptionsBuilder.EnableSensitiveDataLogging для просмотра конфликтующих значений ключа.
Я не понимаю, почему он говорит, что он уже отслеживается, поскольку я явно использую AsNoTracking()
в моем методе выбора,Что я могу сделать, чтобы это исправить?
Редактировать: Класс 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; }
}
Мой класс контекста выглядит так:
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; }
}
Редактировать 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"
}
Код, который вставляет:
public virtual async Task InsertAsync(TObj obj)
{
_context.Set<TObj>().Add(obj);
await _context.SaveChangesAsync().ConfigureAwait(false);
}