Entity Framework .. Как мне сопоставить внешний ссылочный внешний ключ .. например, Категория имеет много категорий - PullRequest
3 голосов
/ 03 сентября 2010

У меня есть следующий класс поко:

public class Category : IDisplayName
{
    private ICollection<Category> children;
    private Category parent;

    public Category()
    {
        children = new List<Category>();
    }

    public int Id { get; set; }

    public string Name { get; set; }

    public virtual Category Parent
    {
        get { return parent; }
        set
        {
            parent = value;

            // if (value != null && parent.Children.Contains(this) == false)
            // {
            //      parent.Children.Add(this);
            // }
        }
    }

    public virtual ICollection<Category> Children
    {
        get { return children; }
        set { children = value; }
    }
}

Это файл сопоставления (я не уверен, что это правильно ... но у меня нет идей, и там есть вся документация ...)

public class CategoryEntityConfiguration : EntityConfiguration<Category>
{
    public CategoryEntityConfiguration()
    {
        Property(x => x.Name).IsRequired();

        HasMany(x => x.Children).WithOptional(x => x.Parent);
        HasOptional(x => x.Parent).WithMany(x => x.Children);
    }
}

Обратите внимание на свойство "Parent" и то, как я не добавляю их каждый из них с помощью коллекции "Children".

var cat_0 = new Category { Name = "Root" };            
var cat_1 = new Category { Name = "Property", Parent = cat_0 };
var cat_2 = new Category { Name = "Property Services", Parent = cat_1 };
var cat_3 = new Category { Name = "Housing Association", Parent = cat_2 };
var cat_4 = new Category { Name = "Mortgages & Conveyancing", Parent = cat_2 };
var cat_5 = new Category { Name = "Property Management", Parent = cat_2 };
var cat_6 = new Category { Name = "Property Auctions", Parent = cat_2 };
var cat_7 = new Category { Name = "Landlords Wanted", Parent = cat_2 };

context.Set<Category>().Add(cat_0);

Когда я сохраняю cat_0 в базе данных, вставляется только 1 строка, и Entity Framework не улавливает тот факт, что cat_0 является родителем целого ряда других объектов и не понимает, что их необходимо сохранить. У меня есть обходной путь, который представляет собой закомментированный код в свойстве категории «Родитель» ... но я бы предпочел не делать этого, так как он не выглядит правильным.

Любая помощь будет высоко ценится

Jake

1 Ответ

2 голосов
/ 03 сентября 2010

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

public class Category 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual Category Parent { get; set; }
    public virtual ICollection<Category> Children { get; set; } 
} 

Создайте контекст и проверьте, разрешено ли создание динамического прокси. В таком контексте вы можете использовать метод CreateObject, чтобы получить экземпляр вашей категории. Вы не получите экземпляр типа Category, но динамический тип, унаследованный от Category. Этот динамический прокси-сервер отвечает за отложенную загрузку (если она включена) и отслеживание изменений в существующем контексте. Если вы измените свойство навигации с одной стороны, оно автоматически изменит свойство навигации с другой стороны.

using (var context = new ObjectContext(connectionString))
{
  // This should be default value
  context.ContextOptions.ProxyCreationEnabled = true;

  var cat0 = context.CreateObject<Category>();
  cat0.Name = "A";

  var cat1 = context.CreateObject<Category>();
  cat1.Name = "B";
  cat1.Parent = cat0;

  context.CreateObjectSet<Category>().AddObject(cat0);
  context.SaveChanges(); 
}

Edit:

Если вам не нравится подход с отслеживанием прокси (который требует существующего контекста), вы можете изменить способ создания ваших сущностей. Вместо того, чтобы устанавливать свойство Parent для childs, вы должны заполнить Childs для parent. В этом случае это будет работать.

...