【问题标题】:Entity Framework.. How do I map a self referencial foreign key.. eg Category has many Categories实体框架..如何映射自引用外键.. ef 类别有很多类别
【发布时间】:2010-09-03 10:48:48
【问题描述】:

我有以下 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; }
    }
}

这是映射文件(我不确定这是否正确..但我没有想法,所有文档都在那里......)

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

注意“父”属性以及我如何不使用“子”集合添加它们。

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

任何帮助将不胜感激

杰克

【问题讨论】:

    标签: c# entity-framework poco


    【解决方案1】:

    这是可能的,但您必须使用跟踪代理。为此,请修改您的 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(); 
    }
    

    编辑:

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

    【讨论】:

    • 是的,谢谢你的回答,是的,我有点猜想 ObjectContext 在创建时必须知道实体。此外,我正在使用 DbContext 类,该类将 ObjectContext 作为受保护的属性,不确定隐藏 ObjectContext 公开的所有功能背后的原因是什么。想听听关于为什么会这样的任何反馈.. :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多