繁体   English   中英

在模型之间复制数据并保存子项,而实体框架中没有实体重复

[英]Copying data between models and saving children without entities duplicating themselves in Entity Framework

我无法通过Entity Framework / ASP Identity保存子实体。 它似乎是添加了所有内容的重复。

我尝试在TeamMemberModel中使用TeamMember.DrivingLicence = null的DrivingLicenceModel的分离图,然后通过查看是否存在新的或旧的DrivingLicenceCategories来处理分离图,但是因为DrivingLicence链接回TeamMember,它导致TeamMember.DrivingLicenceId为null因为它无法链接回TeamMember。

我试过手动将EntityState添加到DrivingLicence和DrivingLicenceCategories但是当我这样做时,它抱怨它无法保存具有相同主键的两个实体。

我认为这是因为他们的方式我正在复制实体,但我经过很多看后我画了一个空白。

如果无论如何要从TeamMemberRequestModel复制到TeamMemberModel然后保存,孩子们没有尝试创建自己的克隆副本?

楷模

public class TeamMemberModel : IdentityUser
{
    public virtual DrivingLicenceModel DrivingLicence { get; set; }

    public void ShallowCopy(TeamMemberRequestModel src)
    {
         this.DateOfBirth = src.DateOfBirth;

         if (src.DrivingLicence != null)
         {
              if (this.DrivingLicence == null)
              {
                   this.DrivingLicence = new DrivingLicenceModel(src.DrivingLicence);
              }
              else
              {
                   this.DrivingLicence.ShallowCopy(src.DrivingLicence);
              }
         }
     }

     public TeamMemberModel() { }
}

public class DrivingLicenceModel
{
    [Key]
    public int Id { get; set; }

    [ForeignKey("TeamMember")]
    public string TeamMemberId { get; set; } 

    [JsonIgnore]
    public TeamMemberModel TeamMember { get; set; }

    public virtual List<DrivingLicenceCategoryModel> DrivingLicenceCategories { get; set; }

    public DrivingLicenceModel() { }

    public DrivingLicenceModel(DrivingLicenceModel src)
    {
        this.ShallowCopy(src);
    }

    public void ShallowCopy(DrivingLicenceModel src)
    {
        this.Id = src.Id;
        this.IsFullLicence = src.IsFullLicence;
        this.IssueDate = src.IssueDate;
        this.ExpiryDate = src.ExpiryDate;
        this.IssuingAuthority = src.IssuingAuthority;
        this.LicenceNumber = src.LicenceNumber;
        this.DrivingLicenceCategories = src.DrivingLicenceCategories;
        this.DrivingLicencePoints = src.DrivingLicencePoints;
    }
}

public class DrivingLicenceCategoryModel
{
    [Key]
    public int Id { get; set; }

    [ForeignKey("DrivingLicence")]
    public int DrivingLicenceId { get; set; }

    [JsonIgnore]
    public DrivingLicenceModel DrivingLicence { get; set; }
}

public class TeamMemberRequestModel
{
    public string Id { get; set; }

    public virtual DrivingLicenceModel DrivingLicence { get; set; }
}

上下文

public class TIERDBContext : IdentityDbContext<TeamMemberModel, RoleModel, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
{
    public TIERDBContext() : base("SARDBConnection") { }

    public DbSet<DrivingLicenceModel> DrivingLicences { get; set; }
    public DbSet<DrivingLicenceCategoryModel> DrivingLicenceCategories { get; set; }
}

调节器

 public async Task<IHttpActionResult> Put(string id, TeamMemberRequestModel teamMember)
 {
      TeamMemberModel CurrentTeamMember = await this.TIERUserManager.FindByIdAsync(id);

      CurrentTeamMember.ShallowCopy(teamMember);

      await this.TIERUserManager.UpdateAsync(CurrentTeamMember);
 }

您必须在上下文类中创建clone属性。

在上下文条款中,您可以使用克隆方法重新定义您通过参数传递的实体,这个duplicarse传递给您的任何实体。 对不起我的英语不好

希望你能帮忙

经过这么长时间工作了很长时间。 我已经回答了。 处理此问题的最佳方法是简单地处理它是在树中添加或附加所有实体。

控制器现在附加所有子项,除非它们的ID为0,因此new和use使用add。 然后我使用这个非常有用的扩展,我在这里找到http://yassershaikh.com/c-exceptby-extension-method/比较列表,看看列表中添加和删除的实体。 虽然我不需要添加部分,因为实体已经被标记为添加状态,因为我使用add()它不会造成伤害,我想稍后使用它添加和删除状态更改。

调节器

public async Task<IHttpActionResult> Put(string id, TeamMemberRequestModel teamMember)
{
    TIERDBContext IdentityContext = (TIERDBContext)this.TIERUserManager.UserStore().Context;

    foreach (DrivingLicenceCategoryModel DrivingLicenceCategory in teamMember.DrivingLicence.DrivingLicenceCategories)
    {
        if (DrivingLicenceCategory.Id == 0)
        {
            IdentityContext.DrivingLicenceCategories.Add(DrivingLicenceCategory);
        }
        else
        {
            IdentityContext.DrivingLicenceCategories.Attach(DrivingLicenceCategory);
        }
    }

    foreach (DrivingLicencePointModel DrivingLicencePoint in teamMember.DrivingLicence.DrivingLicencePoints)
    {
        if (DrivingLicencePoint.Id == 0)
        {
            IdentityContext.DrivingLicencePoints.Add(DrivingLicencePoint);
        }
        else
        {
             IdentityContext.DrivingLicencePoints.Attach(DrivingLicencePoint);
        }
    }

    this.DetectAddedOrRemoveAndSetEntityState(CurrentTeamMember.DrivingLicence.DrivingLicenceCategories.AsQueryable(),teamMember.DrivingLicence.DrivingLicenceCategories, IdentityContext);

    this.DetectAddedOrRemoveAndSetEntityState(CurrentTeamMember.DrivingLicence.DrivingLicencePoints.AsQueryable(),teamMember.DrivingLicence.DrivingLicencePoints, IdentityContext);

    CurrentTeamMember.ShallowCopy(teamMember);

    await this.TIERUserManager.UpdateAsync(CurrentTeamMember);
}

然后,我使用一个使用ExceptBy的泛型来计算从旧团队成员模型添加和删除的内容到新的团队成员模型。

    protected void DetectAddedOrRemoveAndSetEntityState<T>(IQueryable<T> old, List<T> current, TIERDBContext context) where T : class, IHasIntID
    {
        List<T> OldList = old.ToList();
        List<T> Added = current.ExceptBy(OldList, x => x.Id).ToList();
        List<T> Deleted = OldList.ExceptBy(current, x => x.Id).ToList();

        Added.ForEach(x => context.Entry(x).State = EntityState.Added);
        Deleted.ForEach(x => context.Entry(x).State = EntityState.Deleted);
    }

它有效,但它远非伟大。 它需要两个DB查询,获取原始和更新。 我想不出更好的方法来做到这一点。

暂无
暂无

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

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