首页 > 解决方案 > 使用 Id 属性插入具有多对多的未跟踪实体

问题描述

我有一个包含参考数据和非参考数据的应用程序。

参考数据不会经常更改,因此我们决定缓存它。

因为我们是从缓存中获取的,所以在查询时不会跟踪参考数据。

我现在有一个问题,当我插入一个新的非参考数据实体时,它会尝试插入新的参考数据项。

一个例子:

public class Plant {
    public int Id { get; set; }
    public string Name { get; set; }
    public int FamilyId { get; set; }
    public Family Family { get; set; }
    public ICollection<PlantColour> PlantColours { get; set; }
}

public class Family {
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Plant> Plants { get; set; }
}

public class PlantColour {
    public int PlantId { get; set; }
    public int ColourId { get; set; }
    public Plant Plant { get; set; }
    public Colour Colour { get; set; }
}

public class Colour {
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<PlantColour> PlantColours { get; set; }
}

当它试图插入一个新的植物、家庭属性集时,它会尝试插入一个新的家庭。我们可以通过设置外键字段来解决这个问题Plant.FamilyId = myFamily.Id;

但是,对于像这样的多对多关系Plant.PlantColours,如果我想将颜色与植物相关联,这将不起作用。

特别是,Colours从上下文中被缓存,因此它们不被跟踪。

如果我创建一个新的,请从缓存的颜色中选择每种颜色,并使用我想要的颜色名称,如果我还没有要填充的 PlantId,我Plant该如何创建必要的颜色?plant.PlantColours

我想避免为每条记录再次查询数据库,因为它将处理数千条记录。

标签: c#entity-framework-core

解决方案


您只需要避免对未跟踪对象的任何引用,Id而是使用其字段:

List<Colour> selectedColours = GetSelectedColours(); // colours from cache
Family selectedFamily = GetSelectedFamily(); // family from cache

var plant = new Plant
{
    Name = "Black alder",
    FamilyId = selectedFamily.Id // Family property is null
};

plant.PlantColours = selectedColours.Select(c => new PlantColour
{
    Plant = plant,
    ColourId = c.Id // Colour property is null
}).ToList();

myDbContext.Set<Plant>.Add(plant);
await myDbContext.SaveChangesAsync();

推荐阅读