简体   繁体   English

Entity Framework Core 添加具有已保存依赖项的实体会引发错误

[英]Entity Framework Core Add entity with dependecy that is saved throws the error

I have something like this entities:我有这样的实体:

class Store
{
    public int Id { get; set; }
    public List<StoreItem> Items { get; set; }
    ...
}
class Item
{
    public int Id { get; set; }
    ...
}
class StoreItem 
{
    public int ItemId { get; set; }
    public Item Item { get; set; }
    public int StoreId { get; set; }
    public Store Store { get; set; }
}

When I added to store saved item and then try to add it to DbSet:当我添加到存储保存的项目然后尝试将其添加到 DbSet 时:

Item item = new Item()
{
    ...
};
using (var transaction = _dbContext.Database.BeginTransaction())
{
    await _dbContext.Items.AddAsync(item); // The item is stored in store StoreItem
    await _dbContext.SaveChangesAsync();
}
...
Store store = new Store()
{
    ...
};
store.Items = new List<StoreItem>()
{
    new StoreItem()
    {
        ItemId = item.Id,
        Item = item,
        Store = store,
    }
};
using (var transaction = _dbContext.Database.BeginTransaction())
{
    await _dbContext.Stores.AddAsync(store);
    await _dbContext.SaveChangesAsync();
}

this code throws exception that:此代码引发异常:

The instance of entity type 'Item' 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.

I cannot get how to add new Store that have dependency on already saved Item ??我无法了解如何添加依赖于已保存项目的新商店?

Issue is reproducible on PostgresSQL, here is project example https://github.com/redradist/SO-ReproducedExample问题可在 PostgresSQL 上重现,这里是项目示例https://github.com/redradist/SO-ReproducedExample

DbSet<T>.Add will assume that all objects that have not been tracked yet are new. DbSet<T>.Add将假定尚未跟踪的所有对象都是新对象。

If you want to attach your Item as an existing item, you should do that first, or use context.ChangeTracker.TrackGraph() so you can specify how each object should be attached.如果您想将您的 Item 作为现有项目附加,您应该首先执行此操作,或者使用context.ChangeTracker.TrackGraph()以便您可以指定应如何附加每个对象。

Issue was due to that in example https://github.com/redradist/SO-ReproducedExample I used different objects for the same Many-to-Many relationship:问题是由于在示例https://github.com/redradist/SO-ReproducedExample 中,我为相同的多对多关系使用了不同的对象:

var storesForItem1 = new List<StoreItemEntity>()
{
    new StoreItemEntity()
    {
        ItemId = item1Entity.Id,
        Item = item1Entity,
        Store = storeEntity,
    }
};
var storesForItem2 = new List<StoreItemEntity>()
{
    new StoreItemEntity()
    {
        ItemId = item2Entity.Id,
        Item = item2Entity,
        Store = storeEntity,
    }
};
var itemsForStore = new List<StoreItemEntity>()
{
    new StoreItemEntity()  // <-- Issue, should be used previous created StoreItemEntity for this relationship
    {
        Item = item1Entity,
        StoreId = storeEntity.Id,
        Store = storeEntity,
    },
    new StoreItemEntity()  // <-- Issue, should be used previous created StoreItemEntity for this relationship
    {
        Item = item2Entity,
        StoreId = storeEntity.Id,
        Store = storeEntity,
    }
};

You should use only one entity instance with the same key for particular object对于特定对象,您应该只使用一个具有相同键的实体实例

Here is fixed implementation in branch fixed-example :这是分支fixed-example固定实现:

https://github.com/redradist/SO-ReproducedExample/tree/feature/fixed-example https://github.com/redradist/SO-ReproducedExample/tree/feature/fixed-example

- 1 - 1

Most of the time this exception is related with Service Registration大多数情况下,此异常与Service Registration

And most likely - because you didnt provide more information - your repository/service is registered as a singleton lifetime并且很可能 - 因为您没有提供更多信息 - 您的存储库/服务被注册为单例生命周期

-> Startup.cs - services.AddSingleton<IRepository, Repository>(); -> Startup.cs - services.AddSingleton<IRepository, Repository>();

You have to change it to services.AddScoped<IRepository, Repository>();您必须将其更改为services.AddScoped<IRepository, Repository>();

- 2 - 2

This could be happening because of you are sharing your entity accross multiple DbContext objects.这可能是因为您正在DbContext多个DbContext对象共享您的实体。

Please try to use one context for your method.请尝试为您的方法使用一种上下文。

- 3 - 3

AsNoTracking() could be helpful, but while you are adding a new entity I don't think that this is the best situation. AsNoTracking()可能会有所帮助,但是当您添加新实体时,我认为这不是最好的情况。

Among all of the above, I think the source of the problem is what I explained in the 1st point.综上所述,我认为问题的根源是我在第一点中所解释的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM