Кодекс ADO EF - первый двунаправленный вызов для многих - PullRequest
0 голосов
/ 23 апреля 2011

Я пинал шины по ADO EF Code First и столкнулся со следующей проблемой:

Моя модель просто представляет собой семейное древо.Он состоит из класса Person с несколькими скалярными свойствами FirstName и т. Д. И коллекции Person, представляющей родителей, и другой коллекции Person, представляющей детей.

public class Person
{
    public int id { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public DateTime? DateOfBirth { get; set; }

    List<Person> children = new List<Person>();
    public IList<Person> Children { get { return children; } set { children = (List<Person>)value; } }

    List<Person> parents = new List<Person>();
    public IList<Person> Parents { get { return parents; } set { parents = (List<Person>)value; } }
}

Код контекста довольно прост

public class DataContext : DbContext
{
    public DbSet<Person> People { get; set; }
}

Созданная схема базы данных соответствует ожидаемой.Таблица людей с двумя связями один-ко-многим с таблицей с именем PersonPersons.(Кстати, есть ли способ изменить это на таблицу с именем FamilyTree?)

Затем я перехожу к Seed the DataBase с некоторыми данными, семейному дереву для мультипликационного шоу Popular Simpsons.Я создаю всех нужных мне людей, связываю их, а затем сохраняю переменную person, представляющую Гомера Симпсона.

class ProjectDBInitializer : DropCreateDatabaseIfModelChanges<DataContext>
{
    protected override void Seed(DataContext context)
    {
        Person ph = new Person() { FirstName = "Homer", LastName = "Simpson" };
        Person pm = new Person() { FirstName = "Marge", LastName = "Simpson" };

        Person pb = new Person() { FirstName = "Bart", LastName = "Simpson" };
        Person pl = new Person() { FirstName = "Lisa", LastName = "Simpson" };

        Person phf = new Person() { FirstName = "GranPa", LastName = "Simpson" };
        Person phm = new Person() { FirstName = "GranMa", LastName = "Simpson" };

        Person pmf = new Person() { FirstName = "Marge Father", LastName = "Maiden" };
        Person pmm = new Person() { FirstName = "Marge Mother", LastName = "Maiden" };

        phf.Children.Add(ph);
        phm.Children.Add(ph);

        ph.Children.Add(pb);
        ph.Children.Add(pl);

        pb.Parents.Add(ph);
        pb.Parents.Add(pm);

        pl.Parents.Add(ph);
        pl.Parents.Add(pm);

        pm.Parents.Add(pmf);
        pm.Parents.Add(pmm);

        context.People.Add(ph);
        context.SaveChanges();
    }
}

Проблема возникает, когда я смотрю на то, что вошло в базу данных.

Все члены семьи Мардж были добавлены, а родители Гомера (GranPa и GranMa) - нет.Я предполагаю, что это связано с тем фактом, что ph varibale не имеет к ним ссылки, даже если они содержат ссылку на него в своей коллекции Children.

Каков наилучший (самый простой) способ решения этой проблемы?проблема?

1 Ответ

2 голосов
/ 23 апреля 2011

Чтобы восстановить таблицу, вы должны добавить свободное сопоставление с вашим контекстом:

public class DataContext : DbContext
{
    public DbSet<Person> People { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Person>()
            .HasMany(p => p.Children)
            .WithMany(c => c.Parents)
            .Map(m => m.ToTable("FamilyTree"));
    }
}

Проблема со вставкой точно такая, как вы описали. Если вы хотите вставить Гомера, вы должны установить phf и phm в качестве его родителей, или вы должны добавить phm и phf в People, точно так же, как вы добавили Гомера.

Автоматически сгенерированные объекты POCO (шаблоны T4, используемые для генерации POCO из EDMX) используют более сложный код для свойств навигации и внутренне обрабатывают исправление отношений, поэтому, если вы добавляете Homer в дочернюю коллекцию в phm, это, в свою очередь, автоматически добавляет phm к родителям Homer. , Если вам нужна такая функциональность в ваших собственных POCO, вы должны реализовать ее самостоятельно. Методы исправления не всегда являются беспроигрышным решением, потому что они имеют некоторый недостаток и иногда вызывают отложенную загрузку без реальной необходимости загружать данные.

...