处理NHibernate父子集合的最佳实践
因此,在一个典型的模型中,如果父对象可以有多个子对象,而子对象只能有一个父对象,那么如何管理子对象的添加。我一直在使用这种方法处理NHibernate父子集合的最佳实践,nhibernate,domain-driven-design,Nhibernate,Domain Driven Design,因此,在一个典型的模型中,如果父对象可以有多个子对象,而子对象只能有一个父对象,那么如何管理子对象的添加。我一直在使用这种方法 public class Parent { public Parent() { Children = new List<Child>(); } public IList<Child> Children { get; private set; } }
public class Parent
{
public Parent()
{
Children = new List<Child>();
}
public IList<Child> Children
{
get;
private set;
}
}
public class Child
{
public Parent Parent
{
get;
set;
}
}
var child = new Child();
var parent = new Parent();
parent.Children.Add(child);
child.Parent = parent;
公共类父类
{
公共家长()
{
Children=新列表();
}
公营儿童
{
得到;
私人设置;
}
}
公营儿童
{
公共家长
{
得到;
设置
}
}
var child=new child();
var parent=新父级();
parent.Children.Add(child);
child.Parent=Parent;
问题是,无论我想在哪里添加一个新的孩子,我都必须记住添加对孩子和家长的引用,这有点痛苦。我可以向父类添加一个AddChild方法,并让它负责添加子类-现在的问题是,有两种方法可以通过children属性和方法添加子类。那么这是一个更好的解决方案吗
public class Parent
{
public Parent()
{
children = new List<Child>();
}
private IList<Child> children
{
get;
private set;
}
public IEnumerable<Child> Children
{
get
{
return children;
}
}
public void AddChild(Child child)
{
children.Add(child);
child.Parent = this;
}
}
公共类父类
{
公共家长()
{
children=新列表();
}
私人儿童
{
得到;
私人设置;
}
可数儿童的公共教育
{
得到
{
返回儿童;
}
}
公共无效添加子对象(子对象)
{
添加(child);
child.Parent=this;
}
}
关于这方面的最佳实践有什么指南吗?你是怎么做的?这根本不是NHibernate的问题 您应该实现AddChild方法。这些类负责它们的一致性,因此它们不应该公开任何不可用的内容。例如,(可变)子列表应该隐藏。公开IEnumerable是个好主意 您的第二个代码是一个很好的起点。您可能还需要一些方法,如RemoveChild或ConcountChildren。我是这样做的:
public class Parent
{
private ISet<Child> _children = new HashedSet<Child>();
public ReadOnlyCollection<Child> Children
{
get{ return new List(_children).AsReadOnly(); }
}
public void AddChild( Child c )
{
if( c != null && !_children.Contains (d) )
{
c.Parent = this;
_children.Add (c);
}
}
}
公共类父类
{
私有ISet_children=new HashedSet();
公共只读集合子项
{
获取{返回新列表(_children).AsReadOnly();}
}
公共无效添加子项(子项c)
{
如果(c!=null&&!\u children.Contains(d))
{
c、 父=此;
_添加(c);
}
}
}
所以,事实上,斯特凡也是这么说的。我只公开子列表的只读副本,这样您就可以轻松地迭代父级的子级,并获得父级的子级数。
必须使用AddChild和RemoveChild成员方法向父级添加和删除子级。我不喜欢所有额外的
AddXXX()
和RemoveXXX()
方法扰乱我的实体接口。相反,我有一个自定义列表,在调用Add()
和Remove()
方法时引发事件
然后在事件处理程序中进行链接:
public class Course()
{
public Course()
{
this.Topics = new EntityList<Topic>();
this.Topics.AddItem += new AddItemEventHandler<Topic>(Topic_AddItem);
this.Topics.RemoveItem += new RemoveItemEventHandler<Topic>(Topic_RemoveItem);
}
public EntityList<Topic> Topics { get; private set; }
private void Topic_AddItem(Topic item, object args)
{
// Replace with your linking code:
EntityLinker.Link(this).With(item, args);
}
private void Topic_RemoveItem(Topic item, object args)
{
// Replace with your unlinking code:
EntityLinker.Unlink(this).From(item, args);
}
}
公共课()
{
公共课程()
{
this.Topics=newentitylist();
this.Topics.AddItem+=新的AddItemEventHandler(Topic\u AddItem);
this.Topics.removietem+=新的removietemeventhandler(Topic\u removietem);
}
公共实体列表主题{get;private set;}
私有无效主题\附加项(主题项、对象参数)
{
//替换为您的链接代码:
EntityLinker.Link(this).With(item,args);
}
私有无效主题\u removietem(主题项、对象参数)
{
//替换为您的取消链接代码:
EntityLinker.Unlink(this).From(项,参数);
}
}
我就是这样做的,只是我不将属性用于私有列表
private IList<Child> _children
public IEnumerable<Child> Children
{
get
{
return children;
}
}
private IList\u子级
可数儿童的公共教育
{
得到
{
返回儿童;
}
}
我正在使用public IEnumerable和Add | Remove方法
但是我不太喜欢它,因为它不直观,而且会影响类的定义
我想知道为什么人们不用CustomCollection覆盖添加、删除和替换功能??(就像MS代码中的所有地方一样)?我支持此问题的公认解决方案,但所提供的解决方案并不完整,因为使用私有字段需要在映射程序中进行一些额外配置。为了其他人的利益,以下是完整的解决方案:
public partial class Test
{
private readonly IList<Child> children = new List<Child>();
public virtual IEnumerable<Child> Children
{
get
{
return children;
}
}
}
公共部分类测试
{
private readonly IList children=new List();
公共虚拟可数子对象
{
得到
{
返回儿童;
}
}
}
请注意,公开的集合必须是虚拟的,NHibernate才能使用它。我还喜欢将其设置为只读字段,在创建类时对其进行初始化,以确保它在所有场景中都存在。以下是关联的映射器:
public class TestMap : ClassMap<Test>
{
...
HasMany(s => s.Children).Access.CamelCaseField();
}
公共类TestMap:ClassMap
{
...
HasMany(s=>s.Children);
}
Access属性告诉NHibernate在将值映射到模型时使用私有字段。Access属性上还有其他选项,允许使用各种命名配置。如果数据库中有外键,并且使用Identity(SQL Server)生成主键,则需要从子项到父项的反向链接。否则,insert将在child上发出抱怨,因为nhibernate需要对父ID来回执行一些操作,但它还没有完成 我们最终做了什么来摆脱反向链接:使用NHibernate HiLo生成器。 这样,NHibernate总是具有插入父/子关系所需的ID
谈到第二个例子,我唯一关心的是如何与Linq to NHibernate合作。由于实际映射的属性现在是私有的,我假设它不可见。有什么想法吗?您可以在映射中指定NHibernte在设置值时应该使用字段而不是属性。(以访问属性为例)是的,我得到的是当Linq到N的时候