代码之家  ›  专栏  ›  技术社区  ›  San Jaisy

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

  •  0
  • San Jaisy  · 技术社区  · 2 年前

    使用带有NSubstitte、xunit和Dapper的asp.net核心7,我得到了如下代码

    控制器

    public async Task UpdateStatus(AuthorityStatusUpdateInputDto input)
            {
                int tenantId = AbpSession.GetTenantId();
                using var connection = _dapperContextBuilder.CreateConnection();
                var query = _dapperContextBuilder.QueryBuilder(new {Id = input.Id, TenantId = tenantId},
                    "SELECT TOP 1 * FROM Authority");
                Authority authority = await connection.QueryFirstOrDefaultAsync<Authority>(query.Item1, query.Item2);
    
                authority.Status = input.Status;
                await _authorityRepository.UpdateAsync(authority);
            }
    

    DapperContextBuilder的接口

    公共接口IDapperContextBuilder

    {
        IDbConnection  CreateConnection();
        (string, DynamicParameters) QueryBuilder(object conditions,  string query);
    }
    

    我嘲笑IDbConnection如下,因为我在这个库中使用Dapper https://github.com/jmg48/NSubstitute.DbConnection 嘲弄 sql查询和内存数据库作为sql Lite

    测验

    private readonly IDbConnection _fakedbConnection;
     public AppService_Tests()
            {
                _fakedbConnection = Substitute.For<IDbConnection>().SetupCommands();
            }
    
             [Fact]
            public async Task Should_UpdateStatus_As_Edit()
            {
                // Arrange
                int id = 1001;
                _tenantId = AbpSession.TenantId ?? 0;
                _userId = AbpSession.UserId ?? 0;
                string query = "SELECT TOP 1 * FROM Authority WHERE Id = @Id AND TenantId = @TenantId AND IsDeleted = 0";
                var connectionFactory = Substitute.For<IDapperContextBuilder>();
                 connectionFactory.CreateConnection().Returns(_fakedbConnection);
                UsingDbContext(async context =>
                {
                    CreateAuthorities(context, _tenantId, _userId);
                    // Simulate Dapper behavior
                    var item = context.Authority.FirstOrDefault(x=> x.Id == id);
                    _fakedbConnection.SetupQuery(query).Returns(item);
                });
    
                var dto = new AuthorityStatusUpdateInputDto()
                {
                    Id = id,
                    Status = AuthorityStatus.Edit
                };
                await _authorityAppService.UpdateStatus(dto);
    
                //Asserts
            }
    

    该值从上下文返回为 var item = context.Authority.FirstOrDefault(x=> x.Id == id) ;但是,异常被抛出如下,并且它只是 对于WEB API的单元测试,它运行良好。

    例外

    System.InvalidOperationException : The instance of entity type 'Authority' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. 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.
       at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.ThrowIdentityConflict(InternalEntityEntry entry)
       at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry, Boolean updateDuplicate)
       at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
       at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
       at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey, Nullable`1 fallbackState)
       at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode`1 node)
       at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)
       at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, Boolean forceStateWhenUnknownKey)
       at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.SetEntityState(InternalEntityEntry entry, EntityState entityState)
       at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.Attach(TEntity entity)
       at Abp.EntityFrameworkCore.Repositories.EfCoreRepositoryBase`3.AttachIfNot(TEntity entity)
       at Abp.EntityFrameworkCore.Repositories.EfCoreRepositoryBase`3.Update(TEntity entity)
       at Abp.EntityFrameworkCore.Repositories.EfCoreRepositoryBase`3.UpdateAsync(TEntity entity)
       at LegalRegTech.MasterData.AuthorityAppService.SetAsDraft(Authority authority, AuthorityStatusUpdateInputDto input) in c:\6clicks\src\LegalRegTech.Application\MasterData\AuthorityAppService.cs:line 967
       at LegalRegTech.MasterData.AuthorityAppService.UpdateStatus(AuthorityStatusUpdateInputDto input) in c:\6clicks\src\LegalRegTech.Application\MasterData\AuthorityAppService.cs:line 639
       at LegalRegTech.Tests.Authority.AuthorityAppService_Tests.Should_UpdateStatus_As_Edit() in c:\6clicks\test\LegalRegTech.Tests\Authority\AuthorityAppService_Tests.cs:line 1042
    --- End of stack trace from previous location ---
    
    0 回复  |  直到 2 年前