簡體   English   中英

注入的 Transient 服務仍然在 DbContext 中跟蹤 ChangeTracker 中的實體

[英]Injected Transient service still tracks entities in ChangeTracker in DbContext

當我插入一個實體時,直接在之后,嘗試更新同一個實體,如下所示:

var insertedTransferId = await _transferDs.Create_Async(transferObject);

//update transfer key
if (insertedTransferId > 0)
{
    transferObject.TransferKey = $"{transferObject.TransferKey}00{insertedTransferId}";
    return await _transferDs.Update_Async(transferObject, true);
}

_transferDS Create_Async(TransferModel 模型)

public async Task<int> Create_Async(TransferModel model)
        {
            try
            {
                var entity = _mapper.Map<Transfer>(model);

                this._repo.Create<Transfer>(entity);
                this._repo.Context.Entry(entity).Reference(nameof(entity.TransferMeta)).IsModified = false;
                var success = await _repo.SaveAsync() > 0 ? true : false;

                if (success)
                    await this.UpdateTransferByTransferId(entity.TransferId);

                return success ? entity.TransferId : 0;
            }
            catch
            {
                throw;
            }
        }

_repo.Create(實體)

public virtual void Create<TEntity>(TEntity entity)
    where TEntity : class
{
    Context.Set<TEntity>().Add(entity);
}

我遇到以下問題:

無法跟蹤實體類型“Transfer”的實例,因為已在跟蹤具有相同鍵值的另一個實例

在初始插入之后, EntityStateAdded 當我更新實體時,它抱怨實體已被跟蹤。

我想,在.Net Core DI() 的幫助下,我可以使用TransientLifetime scope 注入我的上下文、服務等,這意味着,每當我請求我的上下文時,都會提供一個新實例,並且ChangeTracker將是干凈的。 不是這樣。

您可以在下面看到,我正在設置上下文的生命周期以及服務:

//Database context and repository
services.AddDbContext<IMyContext, MyContext>(builder =>
{
    builder.UseSqlServer(connectionString: Configuration.GetConnectionString("myConnection"), sqlServerOptionsAction:  null);
    builder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
    //builder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
    builder.EnableSensitiveDataLogging(true); 
}, ServiceLifetime.Transient);

services.AddTransient<IRepo, Repo>();

我錯過了什么,或者不理解什么?

文檔

短暫的

每次從服務容器請求它們時,都會創建瞬態生命周期服務 (AddTransient)。 這個生命周期最適合輕量級、無狀態的服務。

因此Create_AsyncUpdate_Async方法調用是在_transferDs的同一個實例上調用的,該實例將具有您的數據庫上下文的相同實例,導致_transferDs只需解析MyContext一次。

要檢查它,您可以嘗試將MyContext注入Repo兩次並在CreateUpdate上調用不同的(盡管不要在實際/生產代碼中執行此操作)。

UPD

我如何每次都強制一個新實例?

我認為您不應該,您可以檢查實體是否已被跟蹤或使用Find ,但如果您堅持 - 您可以注冊“工廠”(除了普通注冊)並解決它:

services.AddTransient<Func<IRepo>>(s => () => s.GetRequiredService<IRepo>());

Func<IRepo> repoFactory注入您的類並使用它代替_repo

var repo = _repoFactory();
repo.Create<Transfer>(entity);  
repo.Context.Entry(entity).Reference(nameof(entity.TransferMeta)).IsModified = false;
var success = await repo.SaveAsync() > 0 ? true : false;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM