我理解并接受身份生成器打破了工作单元,因为它需要事先实际提交时的插入,如http://fabiomaulo.blogspot.com/2008/12/identity-never-ending-story.html中所述。我知道替代方案以及为什么它们更好(与手头的问题有关,总的来说)。
我遇到的问题是为什么实施存在,以及这些问题是否影响EF(纯粹的好奇心)。我见过的唯一真正的理由是:"NHibernate needs the identity because every entity in the session (they are called "persistent entities") needs to be identified. The identity is also normally used to determine if the record already exists in the database (unsaved value)."
为什么它必须立即具有价值?为什么它不能在提交发生之前推迟INSERT,提交,检索值,并根据返回的标识更新实体,然后插入/更新/不管它们是什么?
不太重要的问题:EF是否遭受同样的问题?我知道ISession是一个合适的UoW实现; EF没有实现UoW模式,或者它有不同的方法来处理这个问题,如果是,它是什么?
答案 0 :(得分:3)
我不会告诉你为什么在NHibernate中没有延迟插入,但我想NHibernate在你把它放到会话时只需要立即真正的实体身份。
EF不使用这种方法,但这并不意味着EF方法更好。首先,EF没有内置支持身份生成器。你可以implement your own,但由于NH试图避免的问题,它可能有点挑战。
ORM工具实现身份映射,它们要求每个实体都是唯一标识的。 NH可能会立即使用真实身份,而EF可以推迟身份定义并使用一些临时密钥。当在数据库中定义真实身份时使用此临时密钥 - 这意味着MS SQL Server中的IDENTITY
列。 EF仅在将记录插入数据库并查询SCOPE_IDENTIY()
后才知道真实身份。当EF接收到真实密钥时,它会更新实体及其所有关系(FK)以反映真实身份。
这也是该方法的最大缺点--EF必须将单独的往返中的每条记录插入数据库以获取其主键值(EF不支持命令批处理)。在这里,您可以找到与NH最大的区别,它能够使用生成器预生成标识,并将这些DML命令批处理到单个往返数据库。
当您开始使用EF 4.0中引入的FK属性时,在EF中使用临时密钥会产生另一个副作用。一旦使用了FK属性,您必须将PK显式设置为某个唯一的临时值,否则插入两个带有关系的记录将失败并出现异常(您将拥有两个具有默认键值的实体,并且FK属性将无法定义哪个是正确的主体)。
EF旨在使用数据库生成的密钥,而NH则更喜欢应用程序生成的密钥。