Я хочу проверить метод обновления в моей службе, и я не могу, потому что он возвращает мне эту ошибку во время выполнения.
Сообщение: System.InvalidOperationException: экземпляр типа сущности 'Objective' не может бытьотслеживается, поскольку другой экземпляр с тем же значением ключа для {'Id'} уже отслеживается. При подключении существующих объектов убедитесь, что подключен только один экземпляр объекта с данным значением ключа. Рассмотрите возможность использования 'DbContextOptionsBuilder.EnableSensitiveDataLogging', чтобы увидеть конфликтующие ключевые значения.
Это Мой тестовый класс.
public class ObjectiveShould: IClassFixture<TestServiceCollectionFactory>
{
TestServiceCollectionFactory _services;
private readonly IObjectiveService objectiveService;
public ObjectiveShould()
{
_services = TestServiceCollectionFactory.Create();
objectiveService = _services.ObjectiveService;
}
[Fact]
[Trait("Category", "Integration test")]
public async Task Update_Should()
{
InitializeData();
var user = await InitializeUserAndRole("CCC", "member");
var model = new ObjectiveCreateDTO()
{
GoalDueDate = new DateTime(2019, 12, 8),
Goal = 5,
};
var add = await objectiveService.Update(user, model, 1);
var objs = await _services.OrganizationsContext.Objectives.FirstOrDefaultAsync(x => x.Id == add.Id);
Assert.NotNull(objs);
}
private void InitializeData()
{
_services.OrganizationsContext.AddRange(EntityBuilder.GetObjectives());
_services.OrganizationsContext.SaveChanges();
}
private async Task<ApplicationUser> InitializeUserAndRole(string userId, string roleName)
{
var user = _services.UserContext.Set<ApplicationUser>().FirstOrDefault(e => e.Id == userId);
await _services.RoleManager.CreateAsync(new IdentityRole { Id = new Guid().ToString(), Name = roleName });
await _services.UserManager.AddToRoleAsync(user, roleName);
return user;
}
}
Метод обновления в tasksService
public async Task<ObjectiveInfoDTO> Update(ApplicationUser invoker, ObjectiveCreateDTO model, int id)
{
_validate.ValidateUser(invoker, _localizer);
if (!string.IsNullOrEmpty(model.AssigneeId) && model.TeamAssigneeId.HasValue)
{
throw new CustomException("WrongParameter", HttpStatusCode.BadRequest, _localizer["WrongParameter"]);
}
var objective = await _objectiveRepository.GetById(id);
_mapper.Map(model, objective);
await _objectiveRepository.Update(objective);
return _mapper.Map<ObjectiveInfoDTO>(objective);
}
Обновление в репозитории
public async Task Update(T entity)
{
_dbContext.Entry(entity).State = EntityState.Modified;
await _dbContext.SaveChangesAsync();
}
Сбор службы тестирования
public TestServiceCollectionFactory()
{
var services = new ServiceCollection();
var mappingConfig = new MapperConfiguration(mc => {
mc.AddProfile(new DomainToViewModelMappingProfile());
mc.AddProfile(new ViewModelToDomainMappingProfile());
});
mapper = mappingConfig.CreateMapper();
services.AddSingleton(mapper);
services
.AddSingleton<IConfiguration>(new ConfigurationBuilder().Build())
.AddDbContext<UsersContext>(o => o.UseInMemoryDatabase("doerio"))
.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.SignIn.RequireConfirmedEmail = true;
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 8;
})
.AddEntityFrameworkStores<UsersContext>()
.AddDefaultTokenProviders();
services
.AddDbContext<OrganizationsContext>(o => o.UseInMemoryDatabase("doerio"));
services
.AddDbContext<TasksContext>(o => o.UseInMemoryDatabase("doerio"));
services
.AddDbContext<AttributesContext>(o => o.UseInMemoryDatabase("doerio"));
services.AddTransient(typeof(IOrganizationsRepository<>), typeof(OrganizationsRepository<>));
.....
services.AddTransient<IObjectiveService, ObjectiveService>();
var provider = services.BuildServiceProvider();
UserContext = provider.GetRequiredService<UsersContext>();
OrganizationsContext = provider.GetRequiredService<OrganizationsContext>();
UserManager = provider.GetRequiredService<UserManager<ApplicationUser>>();
RoleManager = provider.GetRequiredService<RoleManager<IdentityRole>>();
ObjectiveService = provider.GetRequiredService<IObjectiveService>();
.....
}
public static TestServiceCollectionFactory Create()
{
var services = new TestServiceCollectionFactory();
return services;
}
public void Dispose()
{
UserContext.Database.EnsureDeleted();
UserContext.Dispose();
}
}
И GetObjectives в EntityBuilder
public static List<Objective> GetObjectives()
{
return new List<Objective>
{
new Objective
{
Title = "Obj 1",
PillarId = 1,
AssigneeId = "BBB",
OrganizationId = 3,
....
Goal= 5,
MotivationalMessage ="you can!",
ObjectiveStatus = SharedKernel.Enums.ObjectiveStatus.COMPLETED,
Report = SharedKernel.Enums.Report.PILLAR,
Comments = new List<Comment> { new Comment { Message = "test", CreatedDate= new DateTime(2019, 08, 8) , Edited=false, UserId="AAA"} }
},
new Objective
{
Title = "Obj 2",
PillarId = 1,
AssigneeId = "2",
....
ObjectiveStatus = SharedKernel.Enums.ObjectiveStatus.IN_PROGRESS,
Report = SharedKernel.Enums.Report.STATICS_ONTIMETASKS,
Comments = new List<Comment> { new Comment { Message = "test", CreatedDate= new DateTime(2019, 08, 8) , Edited=false, UserId="AAA"} }
}
};
}
И пробовал с другими операциями, такими как удаление и удаление, и это работалоправильно, проблема возникает, когда я пытаюсь сделать Update.
[Update] В методе GetById внутри Update в сервисе есть такой вызов:
public async Task<T> GetById(int id)
{
return await _dbContext.Set<T>()
//.AsNoTracking()
.FirstOrDefaultAsync(e => e.Id == id);
}
Если я прокомментирую строкуAsNoTracking, то тестовый запуск, но мне нужна эта строка для выполнения моего запроса.
Любые предложения?