簡體   English   中英

具有相同ID的多個對象的實體框架跟蹤問題

[英]Entity Framework tracking issue with multiple objects of the same ID

我在學。

我在.netcoreapp 2.1中使用Microsoft.EntityFrameworkCore ,關鍵是要通過API公開靜態數據。

目前,我將數據保存在json對象中。 讓示例保持簡單,我正在嘗試公開一盤三明治和這些三明治的配料。 三明治有各種類型(百吉餅,長面包,短面包等)

首先,我不能完全確定使用EF是正確的工具,但是由於以后我必須管理那些項目(能夠點菜),我才從那里開始。 如果有更好的工具可以使用,那么我現在不禁聽到,但是現在我的問題是使用EF公開它。

我正在閱讀在應用程序中進行硬編碼的json,並將其用作DbContext的起點。 我只是在構造函數中反序列化它,然后將其加載到我的上下文對象中,然后通過API將其公開。 在todo-list模板項目中就像魅力一樣工作。

看起來是這樣,我剛剛添加了更多的DBSet來滿足需要

public class EatupContext : DbContext
{
    public DbSet<FoodType> Types { get; set; }
    public DbSet<Ingredient> Ingredients { get; set; }
    public DbSet<FoodItem> Items { get; set; }
}

FoodType是一個具有ID和名稱的int Ingredients相同。 項目是三明治,看起來像這樣

public class FoodItem
{
    public int Id { get; set; }
    public string Name { get; set; }
    public FoodType Type { get; set; }
    public IEnumerable<Ingredient> Ingredients { get; set; }
}

在我正在讀取的json(映射方式類似於c#對象)中,所有對象的所有id均從0開始。 因此, Types從0到7,配料從0到105,食品從0到60。

這會導致實體框架的ID跟蹤問題,因為存在多個具有相同ID的對象。 即使它們位於不同的DBSets ,這也讓我感到困惑。 根據我的理解(有缺陷?),兩個表(DBSet?)可以具有重復的ID。 我可以有一個類型為0,成分為0、1、2和3的三明治ID 0,它的類型似乎從0到7,然后成分從8到113,三明治為114,這似乎讓我更加困惑到174。從數據庫的角度來看,這對我來說真的很奇怪。

這是我得到的確切錯誤:

An unhandled exception occurred while processing the request.
InvalidOperationException: The instance of entity type 'Ingredient' 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.

Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap<TKey>.ThrowIdentityConflict(InternalEntityEntry entry) 

使用以下stacktrace:

Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap<TKey>.ThrowIdentityConflict(InternalEntityEntry entry)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap<TKey>.Add(TKey key, InternalEntityEntry entry, bool updateDuplicate)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, bool acceptChanges)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, bool acceptChanges, Nullable<EntityState> forceStateWhenUnknownKey)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode node, bool force)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph<TState>(EntityEntryGraphNode node, TState state, Func<EntityEntryGraphNode, TState, bool> handleNode)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph<TState>(EntityEntryGraphNode node, TState state, Func<EntityEntryGraphNode, TState, bool> handleNode)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState entityState, bool forceStateWhenUnknownKey)
Microsoft.EntityFrameworkCore.DbContext.SetEntityState(InternalEntityEntry entry, EntityState entityState)
Microsoft.EntityFrameworkCore.DbContext.SetEntityStates(IEnumerable<object> entities, EntityState entityState)
Microsoft.EntityFrameworkCore.DbContext.UpdateRange(IEnumerable<object> entities)
Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.UpdateRange(IEnumerable<TEntity> entities)
EatUp.Backend.Controllers.EatupController..ctor(EatupContext context) in EatupController.cs
+
            _context.Items.UpdateRange(completeModel.Items);
lambda_method(Closure , IServiceProvider , object[] )
Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider+<>c__DisplayClass4_0.<CreateActivator>b__0(ControllerContext controllerContext)
Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider+<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

而這發生在控制器的以下代碼中:

    private readonly EatupContext _context;

    public EatupController(EatupContext context)
    {
        _context = context;
        var completeModel = JsonConvert.DeserializeObject<EatUpDataModel>(EatUpDataSet.Complete);

        _context.Items.UpdateRange(completeModel.Items);  //fails here
        _context.Types.UpdateRange(completeModel.Types);
        _context.Ingredients.UpdateRange(completeModel.Ingredients);

        _context.SaveChanges();
    }

如果我使用AddRange ,它也會失敗; 我正在使用Update所以我不必檢查集合是否為空,我只是使用json中的最新數據將其擦除。

我不確定應該采取什么方法,我真的不想手動編輯json,但是我看不到如何告訴EF這些不是我已經在做的對象。

編輯:

我已經手動編輯了所有ID,使其只有唯一的ID,但仍然出現錯誤。

ID出現兩次的唯一時間是在不同的三明治中使用相同的成分時,這應該是可以接受的。

現在我200%困惑,我想念什么?

通常,您不需要告訴EF這些是單獨的對象。 它應該解決。 您可以復制並粘貼您的遷移嗎?

暫無
暫無

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

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