Entity Framework, моделирование Code First и циклическая ссылка

Я уже несколько дней пытаюсь решить эту проблему. Создавая простой проект, иллюстрирующий мою проблему, я наткнулся на возможное решение. Так что это своего рода двойной вопрос.

Но сначала небольшая справочная информация:

Я только начал использовать Entity Framework 4.1 (EF) и Code First для создания моделей для моего проекта ASP.NET MVC. Мне нужны модели, подобные этой:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TestApp.Models
{
    public class Family
    {
        public int ID { get; set; }
        public string Name { get; set; }

        public virtual ICollection Fathers { get; set; }
        public virtual ICollection Mothers { get; set; }
    }

    public class Mother
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int FamilyID { get; set; }

        public virtual ICollection Children { get; set; }
        public virtual Family Family { get; set; }
    }

    public class Father
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int FamilyID { get; set; }

        public virtual ICollection Children { get; set; }
        public virtual Family Family { get; set; }
    }

    public class Child
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int MotherID { get; set; }
        public int FatherID { get; set; }

        public virtual Mother Mother { get; set; }
        public virtual Father Father { get; set; }
    }
}

И DbContext:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;

namespace TestApp.Models
{
    public class TestContext : DbContext
    {
        public DbSet Families { get; set; }
        public DbSet Mothers { get; set; }
        public DbSet Fathers { get; set; }
        public DbSet Children { get; set; }
    }
}

(Прошу простить неудачный пример, это то, что смог придумать мой пятничный жареный мозг.)

В семье может быть несколько матерей и несколько отцы. А у ребенка есть мать и отец. Я поработал с одним из гуру .NET, который согласился, что в этом нет ничего экстраординарного. По крайней мере, насколько мы можем видеть.

Но когда я запускаю код, я получаю следующее исключение:

System.Data.SqlServerCe.SqlCeException: ссылочная связь приведет к циклической ссылке, которая недопустима. [Constraint name = Mother_Family]

Я действительно вижу цикл: Семья - Мать - Дитя - Отец - Семья . Но если бы я сам создавал таблицы базы данных (что я предпочитаю не делать, это то, что мне нравится в Code First), это была бы совершенно правильная структура данных, насколько я могу судить.

Итак, мой первый вопрос: Почему это проблема при первом использовании кода? Есть ли способ указать EF, как правильно обрабатывать цикл?

Затем, когда я писал вначале, при создании простого проекта, иллюстрирующего мою проблему, я случайно наткнулся на возможное решение. Я просто забыл некоторые свойства при определении своих моделей. Для ясности в следующем примере, вместо того, чтобы удалять их, я закомментировал части моделей, которые я забыл:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TestApp.Models
{
    public class Family
    {
        public int ID { get; set; }
        public string Name { get; set; }

        public virtual ICollection Fathers { get; set; }
        public virtual ICollection Mothers { get; set; }
    }

    public class Mother
    {
        public int ID { get; set; }
        public string Name { get; set; }
        // public int FamilyID { get; set; }

        public virtual ICollection Children { get; set; }
        public virtual Family Family { get; set; }
    }

    public class Father
    {
        public int ID { get; set; }
        public string Name { get; set; }
        // public int FamilyID { get; set; }

        public virtual ICollection Children { get; set; }
        public virtual Family Family { get; set; }
    }

    public class Child
    {
        public int ID { get; set; }
        public string Name { get; set; }
        // public int MotherID { get; set; }
        // public int FatherID { get; set; }

        public virtual Mother Mother { get; set; }
        public virtual Father Father { get; set; }
    }
}

Итак, удаление этих эталонных свойств SomethingID , похоже, решает мою проблему. Как вы можете видеть в контроллере примера проекта, на который я ссылаюсь в конце этого поста, я все еще могу циклически перемещаться и делать такие вещи, как mothers.First (). Family.Fathers .First (). Children.First (). Mother.Family.Name без проблем. Но все руководства и примеры по моделированию EF и Code First, на которые я смотрел (например, , это Скотт Гатри ), включают эти свойства, поэтому я считаю неправильным не использовать их.

Итак, мой второй вопрос: Будут ли какие-то недостатки и проблемы, которые я еще не обнаружил при этом?

Загрузите пример проекта здесь: http://blackfin.cannedtuna.org/cyclical-reference-test -app.zip и откройте TestSolution.sln. В примере проекта свойства закомментированы. Раскомментируйте строки в TestModels.cs, чтобы добавить свойства, что приведет к исключению циклической ссылки.

NB: Решение создает и заполняет базу данных SQL CE, расположенную в c: \ TestApp.sdf

Update, Декабрь 2011 г .: Технически я эту проблему так и не решил, но бросил работу и нашел другую работу, где мне не нужно использовать технологии Microsoft. Такого рода решена моя проблема :)

Как служба техподдержки на старом месте писала при устранении проблем: «Был предоставлен обходной путь или решение».

8
задан decibyte 2 December 2011 в 13:51
поделиться