实体框架基本属性映射

时间:2018-10-26 14:07:52

标签: c# entity-framework entity-framework-6 ef-fluent-api

您好,我的映射存在问题。

我有分层结构的课程:

  1. TaxYear
  2. 所有者
  3. 经济单位
  4. 报告
  5. ReportItem
  6. 发票

所有这些类都有一个基类“ BaseEntity”,一个父属性和parent_id属性。

发票父属性不是来自“ ReportItem”类型,因为“ Onwer”具有单独的发票清单,因此类型为“ BaseEntity”。

这很好,我可以用作父级“ ReportItem”和“所有者”。

但是现在我想“移动”父母之间的发票。目前只有从“ ReportItem”到“ ReportItem”。

设置新的父项:

foreach (var invoice in oldReportItem.Invoices)
{
    invoice.Parent = newReportItem;
}
ctx.SaveChanges();

这正常工作,但没有错误。 EF为我的父级属性创建了三列。

  • Owner_Id
  • ReportItem_Id
  • Parent_Id

如果插入发票,则两列将获得相同的ID。效果很好,但是如果您设置了新的父级,则“ Onwer_Id”或ReportItem_Id将设置为null,而Parent_Id将仅被更新。

这是我的问题。我认为我的映射是错误的。谁能帮我吗?

Fluent-Api

modelBuilder.Entity<ReportItem>()
    .HasOptional(p => p.Parent)
    .WithMany(p => p.Items)
    .HasForeignKey(k => k.ParentId)
    .WillCascadeOnDelete(false);

BaseEntity:

public abstract class BaseEntity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    public abstract String GetName();

    public DateTime? CreateDate { get; set; }
    public DateTime? LastEditDate { get; set; }

    public BaseEntity DeepCopy()
    {
        return (BaseEntity)MemberwiseClone();
    }
}

所有者:

public class Owner : BaseEntity
{
    public Owner()
    {
        Items = new ObservableCollection<EconomyUnit>();
        PrivateInvoices = new ObservableCollection<Invoice>();
    }

    [Required]
    public String Name { get; set; }

    [Required]
    public TaxYear Year { get; set; }
    public Guid? YearId { get; set; }

    public ICollection<EconomyUnit> Items { get; private set; }
    public ICollection<Invoice> PrivateInvoices { get; private set; }

    public override string GetName()
    {
        return Name;
    }
}

ReportItem:

public class ReportItem : BaseEntity
{
    public ReportItem()
    {
        Items = new ObservableCollection<Invoice>();
    }

    [Required]
    public String Name { get; set; }

    public ICollection<Invoice> Items { get; private set; }

    public Guid? ParentId { get; set; }
    public Report Parent { get; set; }
}

发票:

public class Invoice: BaseEntity
{
    public String Name { get; set; }

    public Guid? ParentId { get; set; }

    public BaseEntity Parent { get; set; }

}

谢谢 抒情诗

1 个答案:

答案 0 :(得分:0)

好,让我们从OP开始。

  

我有分层结构的课程:

     

纳税年度所有者的经济单位报告ReportItem发票

您的类结构表明TaxYear是可选的,因此它不能是父类(根据定义)。您的某些班级缺失,因此我无法确定其他任何关系是否存在缺陷。以您的陈述为准,您的类将更像这样(为清楚起见删除了外部字段)

public abstract class BaseEntity - Unchanged

public class Owner : BaseEntity
{
    // Parent navigation    
    public Guid YearId { get; set; }
    public virtual TaxYear Year { get; set; }

    // Child navigation
    public virtual ICollection<EconomyUnit> Units { get; private set; }
}

public class EconomicUnit : BaseEntity
{
    // Parent navigation    
    public Guid OwnerId { get; set; }
    public virtual Owner Owner { get; set; }

    // Child navigation
    public virtual ICollection<Report> Reports { get; private set; }
}

public class Report : BaseEntity
{
    // Parent navigation    
    public Guid UnitId { get; set; }
    public virtual EconomicUnit Unit { get; set; }

    // Child navigation    
    public virtual ICollection<ReportItem> Items { get; private set; }
}

public class ReportItem : BaseEntity
{
    // Parent navigation    
    public Guid ReportId { get; set; }
    public virtual Report Report { get; set; }

    // Child navigation    
    public virtual ICollection<Invoice> Invoices { get; private set; }
}

public class Invoice : BaseEntity
{
    // Parent navigation    
    public Guid ReportItemId { get; set; }
    public virtual ReportItem ReportItem { get; set; }
}

如果要查看所有者的发票列表,请尝试以下操作:

dbContext.Invoices.Where(a => a.ReportItem.Report.EconomicUnit.Owner.Id == <parameter>).Include(b => b.ReportItem.Report.EconomicUnit.Owner.TaxYear).ToList();

当然,您可以选择一个新的DTO对象,以反转关系Owner ==>发票。