Here is my test case, I hope it's self explanatory.
[Fact]
public async Task ShouldAllowEntityUpdate()
{
var _tenantRepo = LocalIocManager.Resolve<IRepository<Tenant>>();
Tenant tenant = _tenantRepo.Insert(new Tenant("Tname", "name"));
var _userRepo = LocalIocManager.Resolve<IRepository<User,long>>();
_userRepo.Insert(new User()
{
Tenant = tenant,
Name = "jojo"
});
}
This throws an error because it tries to create a new tenant (again) during the _userRepo.Insert
. It's this supposed to be tracked by EF, and thus know that it is an existing entity?
A copy of a quick repo is here: https://github.com/Worthy7/AspAbpSpa/commit/d40f238480934a472a122d6ca6f5cda7ed8e21cd
Test Name: AspAbpSPAMay.Tests.PkDupBug.ShouldAllowEntityUpdate
Test FullName: AspAbpSPAMay.Tests.PkDupBug.ShouldAllowEntityUpdate
Test Source: C:\Users\Ian\Source\Repos\AspAbpSPAMay\4.6.0\test\AspAbpSPAMay.Tests\PkDupBug.cs : line 13
Test Outcome: Failed
Test Duration: 0:00:04.126
Result StackTrace:
at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
at Microsoft.EntityFrameworkCore.InMemory.Storage.Internal.InMemoryTable`1.Create(IUpdateEntry entry)
at Microsoft.EntityFrameworkCore.InMemory.Storage.Internal.InMemoryStore.ExecuteTransaction(IReadOnlyList`1 entries, IDiagnosticsLogger`1 updateLogger)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList`1 entriesToSave)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Abp.EntityFrameworkCore.AbpDbContext.SaveChanges() in D:\Github\aspnetboilerplate\src\Abp.EntityFrameworkCore\EntityFrameworkCore\AbpDbContext.cs:line 208
at Abp.Zero.EntityFrameworkCore.AbpZeroCommonDbContext`3.SaveChanges() in D:\Github\aspnetboilerplate\src\Abp.ZeroCore.EntityFrameworkCore\Zero\EntityFrameworkCore\AbpZeroCommonDbContext.cs:line 159
at Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.SaveChangesInDbContext(DbContext dbContext) in D:\Github\aspnetboilerplate\src\Abp.EntityFrameworkCore\EntityFrameworkCore\Uow\EfCoreUnitOfWork.cs:line 163
at Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.SaveChanges() in D:\Github\aspnetboilerplate\src\Abp.EntityFrameworkCore\EntityFrameworkCore\Uow\EfCoreUnitOfWork.cs:line 60
at Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.CompleteUow() in D:\Github\aspnetboilerplate\src\Abp.EntityFrameworkCore\EntityFrameworkCore\Uow\EfCoreUnitOfWork.cs:line 77
at Abp.Domain.Uow.UnitOfWorkBase.Complete() in D:\Github\aspnetboilerplate\src\Abp\Domain\Uow\UnitOfWorkBase.cs:line 256
at Abp.Domain.Uow.UnitOfWorkInterceptor.PerformSyncUow(IInvocation invocation, UnitOfWorkOptions options) in D:\Github\aspnetboilerplate\src\Abp\Domain\Uow\UnitOfWorkInterceptor.cs:line 68
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.IRepository`2Proxy_4.InsertOrUpdate(User entity)
at AspAbpSPAMay.Tests.PkDupBug.ShouldAllowEntityUpdate() in C:\Users\Ian\Source\Repos\AspAbpSPAMay\4.6.0\test\AspAbpSPAMay.Tests\PkDupBug.cs:line 23
--- End of stack trace from previous location where exception was thrown ---
Result Message: System.ArgumentException : An item with the same key has already been added. Key: 2
If this is the wrong way to do this, what's the correct way?
Looking at the answer on this other question it seems my tenant entity is getting detached for some reason. Is it because it needs to be in an UOW to keep tracking?
Correct version:
[Fact]
public async Task ShouldAllowEntityUpdate()
{
var unitOfWorkManager = Resolve<IUnitOfWorkManager>();
var _tenantRepo = LocalIocManager.Resolve<IRepository<Tenant>>();
Tenant tenant = _tenantRepo.Insert(new Tenant("Tname", "name"));
//COMMIT CHANGES to GET the new tenant's Id
_unitOfWorkManager.Current.SaveChanges();
var _userRepo = LocalIocManager.Resolve<IRepository<User,long>>();
//Use TenantId to set the tenant.
_userRepo.Insert(new User()
{
TenantId = tenant.Id,
Name = "jojo"
});
}