接受接口进入nHibernate的收集(协方差)问题
我正在ASP.NET MVC应用程序中使用接受接口进入nHibernate的收集(协方差)问题,nhibernate,fluent-nhibernate,c#-4.0,Nhibernate,Fluent Nhibernate,C# 4.0,我正在ASP.NET MVC应用程序中使用Fluent nHibernate作为持久层,我遇到了一些问题 我有一种情况,我需要使用抽象将对象存储到集合中,在这种情况下,如果从纯C#的角度来看,接口是最合乎逻辑的选择 基本上,一个对象(项)可以有需求。需求可以是很多东西。在本机C#情况下,我只需使用以下代码即可完成此任务 interface IRequirement { // methods and properties neccessary for evaluation } class It
Fluent nHibernate
作为持久层,我遇到了一些问题
我有一种情况,我需要使用抽象将对象存储到集合中,在这种情况下,如果从纯C#的角度来看,接口是最合乎逻辑的选择
基本上,一个对象(项
)可以有需求
。需求可以是很多东西。在本机C#情况下,我只需使用以下代码即可完成此任务
interface IRequirement
{
// methods and properties neccessary for evaluation
}
class Item
{
virtual int Id { get; set; }
virtual IList<IRequirement> Requirements { get; set; }
}
那么,有人有什么想法吗?我似乎也不能使用泛型,所以创建一个基本的需求
类型似乎不太合适。我的意思是代码可以工作和运行,但ORM无法掌握它。我意识到我在这里问的可能是不可能的,但我能做的就是问
我还想补充一点,我在nHibernate
方面没有太多经验,只有Fluent nHibernate
,但我已经意识到这两个社区都非常好,因此我将其标记为两者。但我目前的映射是100%的“流畅”
编辑
事实上,我发现它有点涉及到这一点,但我仍然不确定它是否适用于我的场景。感谢您的帮助
更新(2011年2月2日)
我添加此更新是为了回应发布的一些答案,因为我的结果是。。。有点尴尬
我接受了建议,做了更多的研究,设计了一个基本的界面
interface IRequirement
{
// ... Same as it always was
}
现在我建立了我的类映射
class IRequirementMap : ClassMap<IRequirement>
{
public IRequirementMap()
{
Id( x => x.Id );
UseUnionSubclassForInheritanceMapping();
Table("Requirements");
}
}
尝试添加到该集合失败(正如我预期的那样)。这就是为什么我感到困惑
- 如果我可以在会话中添加到generic
,为什么不在对象中添加呢IList
- nHibernate如何理解具有相同Id的两个实体之间的差异, 如果它们都映射为同一种对象,在一种场景中,而不是在另一种场景中
子类映射
,但问题是标识的数量和表的大小。如果多个对象(最多8个)引用一个表中的标识,我会担心可伸缩性和性能。有人能给我一些具体的见解吗
请查看参考文档中的章节。在本章中,您可以看到使用哪种映射策略可以实现什么 据我所知,您选择了一种“每个具体类的表”策略。您可能需要
和inverse=true
或
来映射它
如果要避免这种情况,需要将irerequirement
作为基类映射到一个表中,然后可以将外键映射到该表中。这样,您就可以将其转换为“每个类的表层次结构”或“每个子类的表”映射。如果已经映射了另一个基类,这当然是不可能的。例如,某种对象
编辑:有关
使用逆=true和
的更多信息
当您使用
时,外键实际上位于指向项目的需求表中。到目前为止,这种方法效果很好,可以使用所有需求表来查找列表中的所有项。反转是必需的,因为它强制您拥有从需求到项目的引用,NH使用该引用构建外键
更灵活。它将列表存储在附加的链接表中。此表有三列:
- 项的外键
- 实际需求类型的名称(.NET类型或实体名称)
- 以及需求的主键(不能是外键,因为它可能指向不同的表)
当NH读取此表时,它从类型信息(以及相应的需求映射)中知道需求所在的其他表。这就是任何类型的工作方式
它实际上是一个多对多关系,这不应该困扰您,它只意味着它将该关系存储在一个附加表中,从技术上讲,该表能够将需求链接到多个项目
编辑2:异常结果:
您映射了3个表:irerequirement
,实现requirement
的对象,另一个具有requirement
的对象。他们都是完全独立的。您仍然在“每个具有隐式多态性的具体类的表”上。您刚刚添加了另一个包含irerequirements
的表,当NH试图找到正确的表时,这也可能导致一些歧义
当然,结果是1,1。具有独立的表,因此具有以1开头的独立ID
起作用的部分:NHibernate在查询接口时,能够在整个数据库中找到实现接口的所有对象。尝试session.CreateQuery(“从对象”)
可以得到整个数据库
不起作用的部分:另一方面,您不能仅通过id和接口或对象
获取对象。因此,session.Get(1)
不起作用,因为有许多id为1的对象。列表也存在同样的问题。还有一些问题,例如,对于隐式多态性,没有指定从实现irerequirement
的每个类型指向项的外键
任意类型:这就是任意类型映射的用武之地。任何类型都与其他类型信息一起存储在数据库中,这是由
映射完成的,该映射将外键和类型信息存储在其他表中。有了这些额外的类型信息,NH就能够找到存储记录的表
怪胎队
class IRequirementMap : ClassMap<IRequirement>
{
public IRequirementMap()
{
Id( x => x.Id );
UseUnionSubclassForInheritanceMapping();
Table("Requirements");
}
}
class ObjectThatImplementsRequirementMap : ClassMap<ObjectThatImplementsRequirement>
{
ObjectThatImplementsRequirementMap()
{
Id(x => x.Id); // Yes, I am base-class mapping it.
// other properties
Table("ObjectImplementingRequirement");
}
}
class AnotherObjectThatHasRequirementMap : ClassMap<AnotherObjectThatHasRequirement>
{
AnotherObjectThatHasRequirementMap ()
{
Id(x => x.Id); // Yes, I am base-class mapping it.
// other properties
Table("AnotheObjectImplementingRequirement");
}
}
// setup ISession
// setup Transaction
var requirements = new <IRequirement>
{
new ObjectThatImplementsRequirement
{
// properties, etc..
},
new AnotherObjectThatHasRequirement
{
// other properties.
}
}
// add to session.
// commit transaction.
// close writing block.
// setup new session
// setup new transaction
var requireables = session.Query<IRequirable>();
foreach(var requireable in requireables)
Console.WriteLine( requireable.Id );
class SomethingThatHasRequireables
{
// ...
public virtual IList<IRequirement> Requirements { get; set; }
}