Сопоставление базовых свойств Entity Framework

Здравствуйте, у меня проблема с отображением.

У меня есть классы в иерархической структуре:

  1. TaxYear
  2. Владелец
  3. EconomyUnit
  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

Если вы вставите счет-фактуру, оба столбца получат одинаковый идентификатор. Работает нормально, но если вы установите нового родителя, тогда для «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; }

}

Спасибо Lyror


person Lyror    schedule 26.10.2018    source источник
comment
Я думаю, что для правильной загрузки EF необходимо знать разницу между Owners и ReportItems, поскольку они не хранятся в одной таблице. Возможно, объект счета-фактуры должен иметь необязательный родительский элемент ReportItem и необязательный владелец, один всегда будет нулевым   -  person Richard Hubley    schedule 26.10.2018


Ответы (1)


Хорошо, начнем с ОП.

У меня есть классы в иерархической структуре:

Налоговый Год Собственник Экономика Единичный отчет Отчет Элемент Счет-фактура

Структуры ваших классов указывают, что 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, инвертируя отношение Владелец ==> Счета-фактуры.

person John White    schedule 26.10.2018