Самоссылающаяся связь в Entity Framework

#inheritance #entity-framework-4.1 #self-reference

#наследование #entity-framework-4.1 #самоссылка

Вопрос:

Сначала я использую код Entity Framework 4.1, и у меня есть две сущности и один абстрактный класс, от которых наследуются обе сущности.

 public abstract class Customer
{
    public long CustomerId { get; set; }
    public string Rating { get; set; }
    public int FinancialStatusValue { get; internal set; }
}

public class Organization : Customer
{
    public string Name { get; set; }
    public string Name2 { get; set; }
    public string LegalName { get; set; }
    public string OrganizationNumber { get; set; }
    public string Vat { get; set; }
    public string Duns { get; set; }
    public Organization HeadQuarter { get; set; }
    public virtual ICollection<Organization> ChildOrganizations { get; set; }
}
  

Я сопоставляю свою модель с:

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        modelBuilder.Entity<Customer>().ToTable("Customer");
        modelBuilder.Entity<Organization>().ToTable("Organization");

        modelBuilder.Entity<Organization>().HasOptional(h => h.HeadQuarter)
            .WithMany(c => c.ChildOrganizations)
            .HasForeignKey(o => o.ParentId);

 }
  

Затем я запрашиваю организацию, используя:

 var org = ctx.Customers.OfType<Organization>().Single(c => c.CustomerId == 259033);
  

Родительский идентификатор заполняется, но головной офис и дочерние организации всегда имеют значение null.

Чего мне не хватает?

Ответ №1:

Вы можете быстро загрузить свойства навигации, используя Include :

 var org = ctx.Customers.OfType<Organization>()
    .Include(o => o.HeadQuarter)
    .Include(o => o.ChildOrganizations)
    .Single(c => c.CustomerId == 259033);
  

Вы также можете использовать отложенную загрузку, которая будет загружать свойства навигации при первом обращении к ней. Вы должны объявить свои свойства навигации как virtual . (Вы сделали это только для ChildOrganizations , но не для HeadQuarter .)

Имейте в виду, что Include будут загружены только те свойства навигации, которые вы точно указали. Он не будет загружать всю вашу древовидную структуру, т. Е. Не Загружать и т.д. Organization.ChildOrganizations.ChildOrganizations

Комментарии:

1. Спасибо за ваш ответ. Как это работает, если я использую ctx.Database. SqlQuery<T>?

2. @RobinHu: Я понятия не имею. Задайте это лучше как отдельный вопрос («Как выполнить загрузку с помощью SqlQuery?» или что-то в этом роде). Однако я немного сомневаюсь, что это вообще возможно, потому что я считаю, что имена столбцов, которые возвращаются, SqlQuery должны совпадать с именами свойств типа T , а имена свойств связанных объектов не являются именами свойств T . Итак, в основном SqlQuery можно заполнять только скалярные свойства, но не свойства навигации. Но уверен, что это не так.