繁体   English   中英

保存具有多个父项的EF实例

[英]Saving an EF instance which has multiple parents

从业务逻辑对象映射回EF对象时,我遇到的主要问题之一是同一个实例有2个父对象的情况:

在此输入图像描述

(对象为黄色,属性为橙色)

在业务逻辑世界中,这里只有一个Tree对象的实例(它显示为多个父项的子项:Forest和Section)

当我使用AutoMapper将所有内容映射回EF对象时,EF认为有两个独立的树实例(尽管它们具有相同的ID)。 因此,它在DB中创建副本。

管理此方案的正确方法是什么,以便Forest和Section指向DB中相同的Tree记录?

我们是否必须通过手动确保所有附件都被认为是重复的?

不幸的是,EF需要获取Tree对象的相同实例,以便在保存整个Forest图形时将其视为相同(覆盖其平等成员没有帮助),这不是Automapper默认情况下映射对象图形的方式。

但您可以按照映射期间重用现有实例的方式设置Automapper配置:

var config = new MapperConfiguration(cfg =>
{
   cfg.CreateMap<Tree, TreeEF>().PreserveReferences();
});

如果你的bussines模型中的ForestSection有一个对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
{
}

我相信如果你不想在这里重复,那么两个孩子不仅必须引用ID而且还要引用内存中的特定实例,因此EF知道它应该是相同的记录(导航属性)。 否则,您必须先保存父记录,然后在事后将密钥分配给每个子记录。 如果这不是GUID而是自动生成的id,那么您可能需要使用相同的引用。

暂无
暂无

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

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