如何删除nhibernate中只有其id和类型的实体?

如何删除nhibernate中只有其id和类型的实体?,nhibernate,nhibernate-2,Nhibernate,Nhibernate 2,我想知道如何使用NHibernate2.1删除一个只有其ID和类型的实体(如映射中的实体)?如果使用延迟加载,则加载只会创建一个代理 session.Delete(session.Load(type, id)); 使用NH2.1,您可以使用HQL。不确定它实际上是什么样子,但类似这样:请注意,这取决于SQL注入-如果可能,使用参数化查询代替SetParameter() 编辑: 对于Load,您不需要知道Id列的名称 如果您需要了解,可以通过NH元数据获取: sessionFactory.Ge

我想知道如何使用NHibernate2.1删除一个只有其ID和类型的实体(如映射中的实体)?

如果使用延迟加载,则加载只会创建一个代理

session.Delete(session.Load(type, id));
使用NH2.1,您可以使用HQL。不确定它实际上是什么样子,但类似这样:请注意,这取决于SQL注入-如果可能,使用参数化查询代替SetParameter()


编辑:

对于Load,您不需要知道Id列的名称

如果您需要了解,可以通过NH元数据获取:

sessionFactory.GetClassMetadata(type).IdentifierPropertyName

另一次编辑

session.Delete()
正在实例化实体

使用session.Delete()时,NH仍会加载实体。一开始我不喜欢它。然后我意识到了它的优点。如果实体是使用继承、集合或“任意”引用的复杂结构的一部分,那么它实际上效率更高

例如,如果类
A
B
都继承自
Base
,则当实际实体的类型为
A
时,它不会尝试删除表
B
中的数据。如果不加载实际对象,这是不可能的。当存在许多继承类型时,这一点尤其重要,这些继承类型还包括许多附加表

当您有一个
Base
s的集合时,也会出现同样的情况,这些集合恰好是
a
的所有实例。在内存中加载集合时,NH知道它不需要删除任何
B
-内容

如果实体
A
B
s的集合,其中包含
C
s(依此类推),则当
B
s的集合为空时,它不会尝试删除任何
C
s。这只有在阅读收藏时才可能。当C本身很复杂,聚集更多的表等等时,这一点尤为重要

结构越复杂和动态,加载实际数据的效率就越高,而不是“盲目”删除数据

HQL删除有陷阱

HQL删除以不将数据加载到内存。但是HQL删除并没有那么聪明。它们基本上将实体名转换为相应的表名,并将其从数据库中删除。此外,它还删除一些聚合的集合数据

在简单的结构中,这可能工作良好且高效。在复杂的结构中,并非所有内容都被删除,从而导致违反约束或“数据库内存泄漏”

结论


我还尝试用NH优化删除。我在大多数情况下都放弃了,因为NH仍然更聪明,它“只是工作”而且通常足够快。我编写的最复杂的删除算法之一是分析NH映射定义并从中构建delete语句。而且——毫不奇怪——在删除之前不从数据库读取数据是不可能的。(我只是将其简化为仅加载主键。)

好的,但我不能按原样使用此代码,因为它假定我知道Id列的名称,而我不知道。在给定实际实体CLR类型的情况下,是否可以找到Id列的名称?毕竟,它在映射中。然后,在获得Id列的名称之后,我可以执行HQL。非常感谢,但还是有一个问题。有些实体在其映射中定义实体名称,但不是全部。实体类型始终是已知的。问题在于,当给定在其映射中定义实体名称的实体类型时,GetClassMetadata返回null。因此,调用sessionFactory.GetClassMetadata(类型)时,我得到null。我该怎么办?谢谢。在我看来,我手头一定有实体名称。没有的实体必须提供其CLR类型的全名。我说的对吗?好吧,应该有一个重载,它以类型作为参数?有,但它以它的全名和委托给重载,重载以字符串作为参数,而字符串又在字典中查找实体名到类元数据的映射。因此,如果实体在其映射中声明实体名称,则只能通过实体名称获取其元数据。按类型执行,就像我那样返回null。
sessionFactory.GetClassMetadata(type).IdentifierPropertyName