首页 > 解决方案 > 尝试在实体中深度克隆除 Id 之外的行值

问题描述

我的项目实体结构如下所示,带有项目名称和项目编号,以及一些列表对象和属性。

public class DesignProject
{
    [Key, GraphQLNonNullType]
    public string ProjectNumber { get; set; }
    public string Name { get; set; }
    [Column(TypeName = "jsonb")]
    public ProjectSectionStatus SectionStatuses { get; set; } = new ProjectSectionStatus();
    [ForeignKey("AshraeClimateZone"), GraphQLIgnore]
    public Guid? AshraeClimateZoneId { get; set; }
    public virtual AshraeClimateZone AshraeClimateZone { get; set; }
    [Column(TypeName = "jsonb")]
    public List<ProjectObject<classA>> classAList{ get; set; } = new List<ProjectObject<classA>>();
    [Column(TypeName = "jsonb")]
    public List<ProjectObject<classB>> classBList{ get; set; } = new List<ProjectObject<classB>>();
    ...... 
    ......
    ......
   Some more json columns
} 

和这样的project object

public class ProjectObject<T>
{
    public Guid? Id { get; set; }
    public T OriginalObject { get; set; }
    public T ModifiedObject { get; set; }

    [GraphQLIgnore, JsonIgnore]
    public T TargetObject
    {
        get
        {
            return ModifiedObject ?? OriginalObject;
        }
    }
}

ClassA实体结构如下

public class ClassA
{
    public string Edition { get; set; }
    public string City { get; set; }  
}

而且我有一些类似的子实体(ClassA)与上面相同,我想将内容和状态从一个项目实体复制到另一个项目实体。

我有ProjectNumber 1212 的项目实体并且有另一个项目的 ProjectNumber 像 23323 所以我想将整个项目内容从复制121223323。那么有什么方法可以用 C# 实现这一点,我正在使用 .Net Core 和 Entity 框架核心。

在这里,我要复制的源设计项目与目标设计项目具有相同的结构,我可以覆盖目标项目值,并且我不想在此处更新项目编号。

谁能告诉我如何实现这种复制?提前致谢!!

如果我需要为此问题添加任何详细信息,请告诉我

更新:深拷贝相关代码

   public InsertResponse<string> CopyBookmarkproject(string SourceProjectNumber, string destinationProjectNumber)
   {
        var sourceDesignProject = this._dbContext.DesignProject.Where(a => a.ProjectNumber == SourceProjectNumber).SingleOrDefault();
        var destinationProject = this._dbContext.DesignProject.Where(a => a.ProjectNumber == destinationProjectNumber).SingleOrDefault();

        CopyProject(sourceDesignProject, destinationProject);

       // Need to update the Db context at here after deep copy
    }

    private void CopyProject(DesignProject sourceDesignProject, DesignProject destinationProject)
    {
        destinationProject.classAList= sourceDesignProject.classAList; // Not sure whether this copy will works 
        destinationProject.AshraeClimateZone = sourceDesignProject.AshraeClimateZone; // not sure whether this copy will works also 
    }

更新的解决方案 2:

    var sourceDesignProject = this._dbContext.DesignProjects.AsNoTracking()
                                                    .Where(a => a.ProjectNumber == sourceProjectNumber)
                                                    .Include(a => a.PrimaryBuildingType)
                                                    .Include(a => a.AshraeClimateZone).SingleOrDefault();

     var targetDesignProject = this._dbContext.DesignProjects.Where(a => a.ProjectNumber == targetProjectNumber).SingleOrDefault();

     sourceDesignProject.ProjectNumber = targetDesignProject.ProjectNumber;
     sourceDesignProject.SectionStatuses.AirSystemsSectionStatus = Entities.Enums.ProjectSectionStage.INCOMPLETE;
            
     sourceDesignProject.SectionStatuses.CodesAndGuidelinesSectionStatus = Entities.Enums.ProjectSectionStage.INCOMPLETE;
     sourceDesignProject.SectionStatuses.ExecutiveSummarySectionStatus = Entities.Enums.ProjectSectionStage.INCOMPLETE;
     sourceDesignProject.SectionStatuses.ExhaustEquipmentSectionStatus = Entities.Enums.ProjectSectionStage.INCOMPLETE;
     sourceDesignProject.SectionStatuses.InfiltrationSectionStatus = Entities.Enums.ProjectSectionStage.INCOMPLETE;
      

     this._dbContext.Entry(sourceDesignProject).State = EntityState.Modified; // getting the below error at this line
     this._dbContext.SaveChanges(); 
     ok = true;

收到如下错误

The instance of entity type 'DesignProject' cannot be tracked because another instance with the same key value for {'ProjectNumber'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.

标签: c#.netentity-frameworkasp.net-coreentity-framework-core

解决方案


有一个简单而简短的解决方案,.AsNoTracking()用于源输入,将目标分配给ProjectNumber源,然后更改它的EntityStateas Modified。它将所有属性复制到目标条目:

var sourceDesignProject = this._dbContext.DesignProject.AsNoTracking().Where(a => a.ProjectNumber == SourceProjectNumber).SingleOrDefault();
var destinationProject = this._dbContext.DesignProject.Where(a => a.ProjectNumber == destinationProjectNumber).SingleOrDefault();

sourceDesignProject.ProjectNumber = destinationProject.ProjectNumber;
this._dbContext.Entry(sourceDesignProject).State = System.Data.Entity.EntityState.Modified;
this._dbContext.SaveChanges();

确保您的关系属性之前已加载。


推荐阅读