Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF核心:更新对象图复制子实体_C#_Entity Framework Core_Entity Framework Core 2.2 - Fatal编程技术网

C# EF核心:更新对象图复制子实体

C# EF核心:更新对象图复制子实体,c#,entity-framework-core,entity-framework-core-2.2,C#,Entity Framework Core,Entity Framework Core 2.2,我们有一个相当复杂的领域模型,我们使用Entityframework核心作为ORM。更新总是在根实体上执行。如果需要添加或更新子对象,则加载根实体,修改子实体,然后保存根实体。与文件的这一部分类似: 我们使用guid作为实体的id,id是由insert上的数据库生成的 这很有效,但有一个问题我无法解决: 我想向StructureTemplate类型的根实体添加一个新元素(GeneralElementTemplate类型) 我从数据库加载StructureTemplate实体和所有子实体(根实体

我们有一个相当复杂的领域模型,我们使用Entityframework核心作为ORM。更新总是在根实体上执行。如果需要添加或更新子对象,则加载根实体,修改子实体,然后保存根实体。与文件的这一部分类似: 我们使用guid作为实体的id,id是由insert上的数据库生成的

这很有效,但有一个问题我无法解决:

  • 我想向StructureTemplate类型的根实体添加一个新元素(GeneralElementTemplate类型)
  • 我从数据库加载StructureTemplate实体和所有子实体(根实体中已经有一个元素-->请参见屏幕截图#1)
  • 我创建新元素(命名为elementTemplate)
  • 我将新元素添加到根实体的Elements集合中(现在Elements集合中有两个实体-->请参见屏幕截图2)
  • 我在DBContext上调用SaveChanges
  • 一切都保存得很好
  • 但是现在根实体的元素集合中有三个实体!新添加的实体在集合中有两次(请参见屏幕截图#3)
  • 在数据库(SQL Server)中,按预期插入/更新所有内容。操作完成后,根对象有两个元素(而不是三个)

我已经尝试过构建一个小的示例项目来演示这种行为,但是在这个示例项目中,一切都很好。 有人能解释一下发生了什么事吗

结构模板实现:

public class StructureTemplate : Document<StructureTemplate>
{
    private HashSet<GeneralElementTemplate> _elements = new HashSet<GeneralElementTemplate>();

    private HashSet<StructureTemplateTag> _structureTemplateTags = new HashSet<StructureTemplateTag>();

    public StructureTemplate(
        DocumentHeader header,
        uint versionNumber = InitialLabel,
        IEnumerable<GeneralElementTemplate> elements = null)
        : base(header, versionNumber)
    {
        _elements = (elements != null) ? new HashSet<GeneralElementTemplate>(elements) : new HashSet<GeneralElementTemplate>();
    }

    /// <summary>
    /// EF Core ctor
    /// </summary>
    protected StructureTemplate()
    {
    }

    public IReadOnlyCollection<GeneralElementTemplate> Elements => _elements;

    public IReadOnlyCollection<StructureTemplateTag> StructureTemplateTags => _structureTemplateTags;

    public override IReadOnlyCollection<Tag> Tags => _structureTemplateTags.Select(x => x.Tag).ToList();

    public void AddElementTemplate(GeneralElementTemplate elementTemplate)
    {
        CheckUnlocked();

        _elements.Add(elementTemplate);
    }

    public override void AddTag(Tag tag) => _structureTemplateTags.Add(new StructureTemplateTag(this, tag));

    public void RemoveElementTemplate(Guid elementTemplateId)
    {
        CheckUnlocked();

        var elementTemplate = Elements.FirstOrDefault(x => x.Id == elementTemplateId);
        _elements.Remove(elementTemplate);
    }

    public override void RemoveTag(Tag tag)
    {
        var existingEntity = _structureTemplateTags.SingleOrDefault(x => x.TagId == tag.Id);
        _structureTemplateTags.Remove(existingEntity);
    }

    public void SetPartTemplateId(Guid? partTemplateId)
    {
        CheckUnlocked();

        PartTemplateId = partTemplateId;
    }
}
public class StructureTemplateTypeConfiguration : IEntityTypeConfiguration<StructureTemplate>
{
    public void Configure(EntityTypeBuilder<StructureTemplate> builder)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }

        builder
            .Property(e => e.Id)
            .ValueGeneratedOnAdd();

        builder
            .OwnsOne(e => e.Header, headerBuilder =>
            {
                headerBuilder
                    .Property(e => e.Name)
                    .HasConversion<string>(x => x, x => EntityName.ToEntityName(x))
                    .HasMaxLength(EntityName.NameMaxLength)
                    .IsUnicode(false);

                headerBuilder
                    .Property(e => e.Descriptions)
                    .HasConversion(
                        d => JsonConvert.SerializeObject(d.ToStringDictionary()),
                        d => d == null
                        ? TranslationDictionary.Empty
                        : JsonConvert.DeserializeObject<Dictionary<EntityLang, string>>(d).ToTranslationDictionary())
                    .HasMaxLength((int)TranslatedEntry.EntryMaxLength * (Enum.GetValues(typeof(EntityLang)).Length + 1));
            });

        builder
            .Property(e => e.VersionNumber);

        builder
            .HasMany(e => e.Elements)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(StructureTemplate.Elements)).SetPropertyAccessMode(PropertyAccessMode.Field);


        // TAGS
        builder
            .Ignore(e => e.Tags);
        builder
            .HasMany(e => e.StructureTemplateTags);
        builder.Metadata
            .FindNavigation(nameof(StructureTemplate.StructureTemplateTags))
            .SetPropertyAccessMode(PropertyAccessMode.Field);
    }
}
public class StructureElementTemplateTypeConfiguration : IEntityTypeConfiguration<GeneralElementTemplate>
{
    public void Configure(EntityTypeBuilder<GeneralElementTemplate> builder)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }

        builder.ToTable("StructureTemplateElements");

        builder
            .Property(e => e.Id)
            .ValueGeneratedOnAdd();

        builder
            .Property(e => e.Type);

        builder
            .HasMany(e => e.Attributes)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Attributes)).SetPropertyAccessMode(PropertyAccessMode.Field);

        builder
            .HasMany(e => e.Groups)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Groups)).SetPropertyAccessMode(PropertyAccessMode.Field);

        builder
            .HasMany(e => e.Materials)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Materials)).SetPropertyAccessMode(PropertyAccessMode.Field);

        builder
            .HasMany(e => e.Points)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Points)).SetPropertyAccessMode(PropertyAccessMode.Field);

        builder
            .HasMany(e => e.Sections)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Sections)).SetPropertyAccessMode(PropertyAccessMode.Field);
    }
}
公共类结构模板:文档
{
私有HashSet_元素=新HashSet();
私有HashSet _structureTemplateTags=新HashSet();
公共结构模板(
文档标题,
uint版本号=初始标签,
IEnumerable元素=空)
:base(标题、版本号)
{
_elements=(elements!=null)?新建哈希集(elements):新建哈希集();
}
/// 
///EF堆芯导体
/// 
受保护的结构模板()
{
}
公共IReadOnlyCollection元素=>\u元素;
公共IReadOnlyCollection StructureTemplateTags=>\u StructureTemplateTags;
public override IReadOnlyCollection Tags=>_structureTemplateTags.Select(x=>x.Tag.ToList();
公共无效AddElementTemplate(GeneralElementTemplate elementTemplate)
{
选中解锁();
_元素。添加(元素模板);
}
public override void AddTag(Tag Tag)=>\u structureTemplateTags.Add(new StructureTemplateTag(this,Tag));
公共void RemoveElementTemplate(Guid elementTemplateId)
{
选中解锁();
var elementTemplate=Elements.FirstOrDefault(x=>x.Id==elementTemplateId);
_元素。删除(elementTemplate);
}
公共覆盖无效移除标记(标记标记)
{
var existingEntity=_structureTemplateTags.SingleOrDefault(x=>x.TagId==tag.Id);
_structureTemplateTags.Remove(现有实体);
}
公共无效SetPartTemplateId(Guid?partTemplateId)
{
选中解锁();
PartTemplateId=PartTemplateId;
}
}
GeneralElementTemplate实现:

public class StructureTemplate : Document<StructureTemplate>
{
    private HashSet<GeneralElementTemplate> _elements = new HashSet<GeneralElementTemplate>();

    private HashSet<StructureTemplateTag> _structureTemplateTags = new HashSet<StructureTemplateTag>();

    public StructureTemplate(
        DocumentHeader header,
        uint versionNumber = InitialLabel,
        IEnumerable<GeneralElementTemplate> elements = null)
        : base(header, versionNumber)
    {
        _elements = (elements != null) ? new HashSet<GeneralElementTemplate>(elements) : new HashSet<GeneralElementTemplate>();
    }

    /// <summary>
    /// EF Core ctor
    /// </summary>
    protected StructureTemplate()
    {
    }

    public IReadOnlyCollection<GeneralElementTemplate> Elements => _elements;

    public IReadOnlyCollection<StructureTemplateTag> StructureTemplateTags => _structureTemplateTags;

    public override IReadOnlyCollection<Tag> Tags => _structureTemplateTags.Select(x => x.Tag).ToList();

    public void AddElementTemplate(GeneralElementTemplate elementTemplate)
    {
        CheckUnlocked();

        _elements.Add(elementTemplate);
    }

    public override void AddTag(Tag tag) => _structureTemplateTags.Add(new StructureTemplateTag(this, tag));

    public void RemoveElementTemplate(Guid elementTemplateId)
    {
        CheckUnlocked();

        var elementTemplate = Elements.FirstOrDefault(x => x.Id == elementTemplateId);
        _elements.Remove(elementTemplate);
    }

    public override void RemoveTag(Tag tag)
    {
        var existingEntity = _structureTemplateTags.SingleOrDefault(x => x.TagId == tag.Id);
        _structureTemplateTags.Remove(existingEntity);
    }

    public void SetPartTemplateId(Guid? partTemplateId)
    {
        CheckUnlocked();

        PartTemplateId = partTemplateId;
    }
}
public class StructureTemplateTypeConfiguration : IEntityTypeConfiguration<StructureTemplate>
{
    public void Configure(EntityTypeBuilder<StructureTemplate> builder)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }

        builder
            .Property(e => e.Id)
            .ValueGeneratedOnAdd();

        builder
            .OwnsOne(e => e.Header, headerBuilder =>
            {
                headerBuilder
                    .Property(e => e.Name)
                    .HasConversion<string>(x => x, x => EntityName.ToEntityName(x))
                    .HasMaxLength(EntityName.NameMaxLength)
                    .IsUnicode(false);

                headerBuilder
                    .Property(e => e.Descriptions)
                    .HasConversion(
                        d => JsonConvert.SerializeObject(d.ToStringDictionary()),
                        d => d == null
                        ? TranslationDictionary.Empty
                        : JsonConvert.DeserializeObject<Dictionary<EntityLang, string>>(d).ToTranslationDictionary())
                    .HasMaxLength((int)TranslatedEntry.EntryMaxLength * (Enum.GetValues(typeof(EntityLang)).Length + 1));
            });

        builder
            .Property(e => e.VersionNumber);

        builder
            .HasMany(e => e.Elements)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(StructureTemplate.Elements)).SetPropertyAccessMode(PropertyAccessMode.Field);


        // TAGS
        builder
            .Ignore(e => e.Tags);
        builder
            .HasMany(e => e.StructureTemplateTags);
        builder.Metadata
            .FindNavigation(nameof(StructureTemplate.StructureTemplateTags))
            .SetPropertyAccessMode(PropertyAccessMode.Field);
    }
}
public class StructureElementTemplateTypeConfiguration : IEntityTypeConfiguration<GeneralElementTemplate>
{
    public void Configure(EntityTypeBuilder<GeneralElementTemplate> builder)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }

        builder.ToTable("StructureTemplateElements");

        builder
            .Property(e => e.Id)
            .ValueGeneratedOnAdd();

        builder
            .Property(e => e.Type);

        builder
            .HasMany(e => e.Attributes)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Attributes)).SetPropertyAccessMode(PropertyAccessMode.Field);

        builder
            .HasMany(e => e.Groups)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Groups)).SetPropertyAccessMode(PropertyAccessMode.Field);

        builder
            .HasMany(e => e.Materials)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Materials)).SetPropertyAccessMode(PropertyAccessMode.Field);

        builder
            .HasMany(e => e.Points)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Points)).SetPropertyAccessMode(PropertyAccessMode.Field);

        builder
            .HasMany(e => e.Sections)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Sections)).SetPropertyAccessMode(PropertyAccessMode.Field);
    }
}
公共类GeneralElementTemplate:实体 { 私有HashSet_attributes=新HashSet(); 私有HashSet_groups=新HashSet(); 私有HashSet_materials=新HashSet(); 私有HashSet_points=新HashSet(); 私有HashSet_sections=新HashSet()

公共GeneralElementTemplate(
ElementTemplateType类型,
IEnumerable points=null,
IEnumerable sections=null,
IEnumerable materials=null,
IEnumerable groups=null,
IEnumerable属性=空)
:base()
{
类型=类型;
_points=points!=null?新哈希集(points):新哈希集();
_sections=sections!=null?新哈希集(sections):新哈希集();
_materials=materials!=null?新哈希集(materials):新哈希集();
_groups=groups!=null?新建哈希集(组):新建哈希集();
_attributes=属性!=null?新哈希集(属性):新哈希集();
}
/// 
///EF堆芯导体
/// 
受保护的GeneralElementTemplate()
{
}
公共IReadOnlyCollection属性=>\u属性;
公共IReadOnlyCollection组=>\u组;
公共IReadOnlyCollection物料=>\u物料;
公共IReadOnlyCollection点数=>\u点数;
公共IReadOnlyCollection节=>\u节;
public ElementTemplateType类型{get;private set;}
公共虚拟GeneralElementTemplate转世()
{
返回新的GeneralElementTemplate(
类型,
要点,,
部分,
材料,
组,
属性);
}
}
结构模板的实体类型配置:

public class StructureTemplate : Document<StructureTemplate>
{
    private HashSet<GeneralElementTemplate> _elements = new HashSet<GeneralElementTemplate>();

    private HashSet<StructureTemplateTag> _structureTemplateTags = new HashSet<StructureTemplateTag>();

    public StructureTemplate(
        DocumentHeader header,
        uint versionNumber = InitialLabel,
        IEnumerable<GeneralElementTemplate> elements = null)
        : base(header, versionNumber)
    {
        _elements = (elements != null) ? new HashSet<GeneralElementTemplate>(elements) : new HashSet<GeneralElementTemplate>();
    }

    /// <summary>
    /// EF Core ctor
    /// </summary>
    protected StructureTemplate()
    {
    }

    public IReadOnlyCollection<GeneralElementTemplate> Elements => _elements;

    public IReadOnlyCollection<StructureTemplateTag> StructureTemplateTags => _structureTemplateTags;

    public override IReadOnlyCollection<Tag> Tags => _structureTemplateTags.Select(x => x.Tag).ToList();

    public void AddElementTemplate(GeneralElementTemplate elementTemplate)
    {
        CheckUnlocked();

        _elements.Add(elementTemplate);
    }

    public override void AddTag(Tag tag) => _structureTemplateTags.Add(new StructureTemplateTag(this, tag));

    public void RemoveElementTemplate(Guid elementTemplateId)
    {
        CheckUnlocked();

        var elementTemplate = Elements.FirstOrDefault(x => x.Id == elementTemplateId);
        _elements.Remove(elementTemplate);
    }

    public override void RemoveTag(Tag tag)
    {
        var existingEntity = _structureTemplateTags.SingleOrDefault(x => x.TagId == tag.Id);
        _structureTemplateTags.Remove(existingEntity);
    }

    public void SetPartTemplateId(Guid? partTemplateId)
    {
        CheckUnlocked();

        PartTemplateId = partTemplateId;
    }
}
public class StructureTemplateTypeConfiguration : IEntityTypeConfiguration<StructureTemplate>
{
    public void Configure(EntityTypeBuilder<StructureTemplate> builder)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }

        builder
            .Property(e => e.Id)
            .ValueGeneratedOnAdd();

        builder
            .OwnsOne(e => e.Header, headerBuilder =>
            {
                headerBuilder
                    .Property(e => e.Name)
                    .HasConversion<string>(x => x, x => EntityName.ToEntityName(x))
                    .HasMaxLength(EntityName.NameMaxLength)
                    .IsUnicode(false);

                headerBuilder
                    .Property(e => e.Descriptions)
                    .HasConversion(
                        d => JsonConvert.SerializeObject(d.ToStringDictionary()),
                        d => d == null
                        ? TranslationDictionary.Empty
                        : JsonConvert.DeserializeObject<Dictionary<EntityLang, string>>(d).ToTranslationDictionary())
                    .HasMaxLength((int)TranslatedEntry.EntryMaxLength * (Enum.GetValues(typeof(EntityLang)).Length + 1));
            });

        builder
            .Property(e => e.VersionNumber);

        builder
            .HasMany(e => e.Elements)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(StructureTemplate.Elements)).SetPropertyAccessMode(PropertyAccessMode.Field);


        // TAGS
        builder
            .Ignore(e => e.Tags);
        builder
            .HasMany(e => e.StructureTemplateTags);
        builder.Metadata
            .FindNavigation(nameof(StructureTemplate.StructureTemplateTags))
            .SetPropertyAccessMode(PropertyAccessMode.Field);
    }
}
public class StructureElementTemplateTypeConfiguration : IEntityTypeConfiguration<GeneralElementTemplate>
{
    public void Configure(EntityTypeBuilder<GeneralElementTemplate> builder)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }

        builder.ToTable("StructureTemplateElements");

        builder
            .Property(e => e.Id)
            .ValueGeneratedOnAdd();

        builder
            .Property(e => e.Type);

        builder
            .HasMany(e => e.Attributes)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Attributes)).SetPropertyAccessMode(PropertyAccessMode.Field);

        builder
            .HasMany(e => e.Groups)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Groups)).SetPropertyAccessMode(PropertyAccessMode.Field);

        builder
            .HasMany(e => e.Materials)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Materials)).SetPropertyAccessMode(PropertyAccessMode.Field);

        builder
            .HasMany(e => e.Points)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Points)).SetPropertyAccessMode(PropertyAccessMode.Field);

        builder
            .HasMany(e => e.Sections)
            .WithOne();
        builder.Metadata.FindNavigation(nameof(GeneralElementTemplate.Sections)).SetPropertyAccessMode(PropertyAccessMode.Field);
    }
}
公共类结构TemplateTypeConfiguration:IEntityTypeConfiguration
{
公共void配置(EntityTypeBuilder)
{
if(builder==null)
{
抛出新ArgumentNullException(nameof(builder));
}
建设者
.Property(e=>e.Id)
.ValueGeneratedOnAdd();
建设者
.OwnsOne(e=>e.标题,标题生成器=>
{
海德堡
.Property(e=>e.Name)
.HasConversion(x=>x,x=>EntityName.ToEntityName(x))
.HasMaxLength(EntityName.NameMaxLength)
.IsUnicode(假);
海德堡
.Property(e=>e.Descriptions)
.哈斯转换(
d=>JsonConvert.SerializedObject(d.ToString目录()),
d=>d==null
?TranslationDictionary。为空