实体框架..如何映射自引用外键..年龄类别有很多类别

时间:2010-09-03 10:48:48

标签: c# entity-framework poco

我有以下poco类:

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; }
    }
}

这是映射文件(我不确定这是否正确..但我没有想法,并且有bugger所有文档......)

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是一大堆其他对象的父级,并且没有意识到它们需要被持久化。我有一个解决方法,它是“父”类别属性中注释掉的代码..但我宁愿不必这样做,因为感觉不对。

非常感谢任何帮助

杰克

1 个答案:

答案 0 :(得分:2)

这是可能的,但您必须使用跟踪代理。为此,请修改您的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方法获取类别实例。您不会获得类别类型的实例,但继承自类别的动态类型。此动态代理负责延迟加载(如果已启用)以及对现有上下文的更改跟踪。如果您在一侧修改导航属性,它将自动修改另一侧的导航属性。

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(); 
}

修改

如果您不喜欢跟踪代理(需要现有上下文)的方法,您可以改变创建实体的方式。不要在子项上设置Parent属性,而是必须在父项上填充Childs。在那种情况下它会起作用。