当从业务逻辑对象映射回EF对象时,我遇到的一个主要问题是同一个实例有2个父对象的情况:
(对象为黄色,属性为橙色)
在业务逻辑世界中,这里只有一个Tree对象的实例(它显示为多个父项的子项:Forest和Section)
当我使用AutoMapper将所有内容映射回EF对象时,EF认为有两个独立的树实例(尽管它们具有相同的ID)。因此,它会在数据库中创建副本。
管理此方案的正确方法是什么,以便Forest和Section指向数据库中相同的Tree记录?
我们是否必须通过并手动确保所有内容都被附加,这可能被视为重复?
答案 0 :(得分:2)
不幸的是,EF需要获取Tree
对象的相同实例,以便在保存整个Forest
图表时将其视为相同(覆盖其平等成员并不帮助),这不是怎么回事Automapper默认映射对象图。
但您可以按照映射期间重用现有实例的方式设置Automapper配置:
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Tree, TreeEF>().PreserveReferences();
});
如果您的商务模型Forest
和Section
具有对Tree
的同一实例的子引用,则此引用将被保留,并且不会创建重复项。
修改强>
class Program
{
static void Main(string[] args)
{
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Forest, ForestEF>().PreserveReferences();
cfg.CreateMap<Section, SectionEF>().PreserveReferences();
cfg.CreateMap<Tree, TreeEF>().PreserveReferences();
});
var mapper = config.CreateMapper();
var forest = new Forest();
var section = new Section();
var tree = new Tree();
forest.Trees.Add(tree);
forest.Sections.Add(section);
section.Trees.Add(tree);
var result = mapper.Map<Forest, ForestEF>(forest);
Console.WriteLine(object.ReferenceEquals(result.Trees[0], result.Sections[0].Trees[0]));
Console.ReadLine();
}
}
public class Forest
{
public IList<Tree> Trees { get; set; } = new List<Tree>();
public IList<Section> Sections { get; set; } = new List<Section>();
}
public class Section
{
public IList<Tree> Trees { get; set; } = new List<Tree>();
}
public class Tree
{
}
public class ForestEF
{
public IList<TreeEF> Trees { get; set; } = new List<TreeEF>();
public IList<SectionEF> Sections { get; set; } = new List<SectionEF>();
}
public class SectionEF
{
public IList<TreeEF> Trees { get; set; } = new List<TreeEF>();
}
public class TreeEF
{
}
答案 1 :(得分:1)
我相信如果你不想在这里重复,那么两个孩子不仅要引用ID而且还要引用内存中的特定实例,这样EF就知道它应该是相同的记录(导航属性)。否则,您必须先保存父记录,然后在事后将密钥分配给每个子记录。如果这不是GUID而是自动生成的id,那么您可能需要使用相同的引用。