NHibernate:更好地存储对另一个实体或实体 ID 的引用?

NHibernate: Better to store reference to another Entity or the entity's ID?

NHibernate 和 C# 的新手。

我有这两个 classes:

User //Simplified version
{
    private long _id;
    private String _username; // unique
    private ISet<Role> _roles;

    //Properties
}

Role
{
    private long _id;
    private String _name;

    //Properties
}

是存储对 Role class 的引用(如上所述)还是只存储 Role class 的 ID 更好(所以:private ISet<Long> _roles)?为什么?

我应该注意哪些利弊?

嗯,首先 NHibernate 是 ORM

... In object-oriented programming, data management tasks act on object-oriented (OO) objects that are almost always non-scalar values. For example, consider an address book entry that represents a single person along with zero or more phone numbers and zero or more addresses. This could be modeled in an object-oriented implementation by a "Person object" with attributes/fields to hold each data item that the entry comprises: the person's name, a list of phone numbers, and a list of addresses. The list of phone numbers would itself contain "PhoneNumber objects" and so on. The address book entry is treated as a single object by the programming language (it can be referenced by a single variable containing a pointer to the object, for instance). Various methods can be associated with the object, such as a method to return the preferred phone number, the home address, and so on....

其次 - 做 A 还是做 B 更好...将更依赖于用例。

但我可以说,(根据我的经验)如果:

  • 我们的域中 两个对象,例如UserRole
  • 我们可以将它们表示为one-to-many and多对一`(双向映射)

我将始终通过引用映射它们。因为将它们映射为 long ReferenceIdISet<long> ReferenceIds.

没有任何好处

仅映射 ID(我可以想象)的唯一用例是在无状态会话中使用它来获取大量数据。但即使在这种情况下,我们也可以使用投影。

"Storing" ID 对我来说不是个好主意。事实上,数据库模式看起来是一样的,所以存储数据的方式没有区别,只是设计 类 的方式不同而已。与实际对象相比,id 不是很有用。

这里有一些优缺点:

映射ID的优势

  • 您可以更轻松地序列化您的实体,因为对象图到此结束,您不会以序列化太多对象而告终。 (请注意,序列化实体还有一些其他问题,在许多情况下不推荐使用。)

映射对象的优点:

  • 无需 DB 交互即可轻松导航到对象,从而充分利用 ORM(可维护性)。
  • 您可以利用批量大小,这可以避免 N+1 问题,而无需优化问题域中的数据访问(性能和可维护性)

构建域模型时,它应该使用正确的引用而不是使用 id 值,

优势,

  1. 你可以有一个合适的域模型,这样编程就变得更容易了(如果你想获得每个用户的角色名称列表,那么在域模型中它非常简单,而如果你有 id 列表那么它
  2. 易于查询(使用 QueryOver / Linq 或 HQL)
  3. 高效SQL(如果要加载用户和角色,如果使用引用,则可以使用 Future 在单个查询中加载所有,但如果使用 Id,则必须使用多个查询)

只要映射正确,我看不出使用引用有任何缺点。

但是,如果需要在多个会话中存储对象,我宁愿使用实体 ID 或存储的 DTO。例如,如果您想将用户存储在 Web Session 对象中,我不会在那里存储任何域对象,而是存储 Id 或 DTO 对象。