繁体   English   中英

NHibernate和sql timestamp列作为版本

[英]NHibernate and sql timestamp columns as version

我一直绞尽脑汁试图让Nhibernate使用字节数组作为版本映射到sql时间戳。 我实现了一个IUserVersionType,但是Nhibernate在数据库中创建varbinary而不是时间戳。 受Ayende最近关于并发的博客文章的启发,我改变了我的映射,将sql-type指定为时间戳,它完美无缺。 但是我现在面临一个相当奇怪的问题,其中Nhibernate执行插入,获取新版本然后立即尝试进行更新并尝试设置版本列,这是一个sql时间戳失败。

这是我的映射:

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Core.Domain, Version=0.1.3397.31993, Culture=neutral,
PublicKeyToken=94dc7dc697cfcfc0" namespace="Core.Domain.Entities"
default-lazy="false">
 <class name="Contact" table="Contacts" xmlns="urn:nhibernate-
mapping-2.2" optimistic-lock="version" dynamic-insert="true" dynamic-
update="true">
   <id name="Id" type="Int32" column="Id">
     <generator class="identity" />
   </id>
   <version name="Version" type="BinaryBlob" generated="always"
unsaved-value="null">
     <column name="Version" sql-type="timestamp" not-null="false" />
   </version>
   <property name="Title" type="String">
     <column name="Title" length="5" />
   </property>
   <property name="FirstName" type="String">
     <column name="FirstName" not-null="true" length="50" />
   </property>
   <property name="MiddleName" type="String">
     <column name="MiddleName" length="50" />
   </property>
   <property name="LastName" type="String">
     <column name="LastName" not-null="true" length="50" />
   </property>
   <property name="Suffix" type="String">
     <column name="Suffix" length="5" />
   </property>
   <property name="Email" type="String">
     <column name="Email" length="50" />
   </property>
   <bag name="PhoneNumbers" inverse="true" cascade="all-delete-
orphan">
     <key foreign-key="FK_Contacts_PhoneNumbers_ContactId" on-
delete="cascade" column="ContactId" />
     <one-to-many class="Core.Domain.Entities.PhoneNumber,
Core.Domain, Version=0.1.3397.31993, Culture=neutral,
PublicKeyToken=94dc7dc697cfcfc0" />
   </bag>
   <property name="DateCreated" type="DateTime">
     <column name="DateCreated" />
   </property>
   <property name="DateModified" type="DateTime">
     <column name="DateModified" />
   </property>
   <property name="LastModifiedBy" type="String">
     <column name="LastModifiedBy" />
   </property>
 </class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Core.Domain, Version=0.1.3397.31993, Culture=neutral,
PublicKeyToken=94dc7dc697cfcfc0" namespace="Core.Domain.Entities"
default-lazy="false">
 <class name="Customer" table="Customers" xmlns="urn:nhibernate-
mapping-2.2" optimistic-lock="version" dynamic-insert="true" dynamic-
update="true">
   <id name="Id" type="Int32" column="Id">
     <generator class="identity" />
   </id>
   <version name="Version" type="BinaryBlob" generated="always"
unsaved-value="null">
     <column name="Version" sql-type="timestamp" not-null="false" />
   </version>
   <property name="AccountNumber" access="nosetter.pascalcase-
underscore" type="String">
     <column name="AccountNumber" unique="true" length="25" />
   </property>
<!-- other mappings... -->
   <property name="DateCreated" type="DateTime">
     <column name="DateCreated" />
   </property>
   <property name="DateModified" type="DateTime">
     <column name="DateModified" />
   </property>
   <property name="LastModifiedBy" type="String">
     <column name="LastModifiedBy" />
   </property>
   <joined-subclass name="Core.Domain.Entities.Individual,
Core.Domain, Version=0.1.3397.31993, Culture=neutral,
PublicKeyToken=94dc7dc697cfcfc0" table="Individuals">
     <key column="CustomerId" />
     <many-to-one fetch="join" lazy="false" not-null="true"
cascade="all" unique="true" not-found="exception" name="Contact"
column="ContactID" />
     <bag name="Addresses" table="Addresses_Individuals">
       <key column="AddressId" foreign-
key="FK_Addresses_Individuals_Addresses_AddressId" />
       <many-to-many column="IndividualId"
class="Core.Domain.Entities.Address, Core.Domain,
Version=0.1.3397.31993, Culture=neutral,
PublicKeyToken=94dc7dc697cfcfc0" foreign-
key="FK_Addresses_Individuals_Individuals_IndividualId" />
     </bag>
   </joined-subclass>
   <joined-subclass name="Core.Domain.Entities.Store, Core.Domain,
Version=0.1.3397.31993, Culture=neutral,
PublicKeyToken=94dc7dc697cfcfc0" table="Stores">
     <key column="CustomerId" />
     <many-to-one unique="true" cascade="save-update" fetch="join"
not-null="true" not-found="exception" name="Address"
column="AddressId" />
     <many-to-one lazy="proxy" not-null="true" cascade="all" not-
found="exception" name="Client" column="ClientId" />
     <property name="StoreName" type="String">
       <column name="StoreName" not-null="true" length="50" />
     </property>
     <bag name="Contacts" table="Contacts_Stores">
       <key column="ContactId" foreign-
key="FK_Contacts_Stores_Contacts_ContactId" />
       <many-to-many column="StoreId"
class="Core.Domain.Entities.Contact, Core.Domain,
Version=0.1.3397.31993, Culture=neutral,
PublicKeyToken=94dc7dc697cfcfc0" foreign-
key="FK_Contacts_Stores_Stores_StoreId" />
     </bag>
   </joined-subclass>
 </class>
</hibernate-mapping>

在具有关联联系人的个人上调用Session.Save会导致以下错误:

NHibernate: INSERT INTO Addresses (Line1, PostalCode, Country,
DateCreated, DateModified, LastModifiedBy) VALUES (@p0, @p1, @p2, @p3,
@p4, @p5); select SCOPE_IDENTITY(); @p0 = 'Order Address Line 1', @p1
= 'CV31 6BW', @p2 = 'United Kingdom', @p3 = '20/04/2009 19:45:32', @p4
= '20/04/2009 19:45:32', @p5 = ''
NHibernate: SELECT address_.Version as Version22_ FROM Addresses
address_ WHERE address_.Id=@p0; @p0 = '1'
NHibernate: INSERT INTO Contacts (FirstName, LastName, DateCreated,
DateModified, LastModifiedBy) VALUES (@p0, @p1, @p2, @p3, @p4); select
SCOPE_IDENTITY(); @p0 = 'Joe', @p1 = 'Bloggs', @p2 = '20/04/2009
19:45:34', @p3 = '20/04/2009 19:45:34', @p4 = ''
NHibernate: SELECT contact_.Version as Version33_ FROM Contacts
contact_ WHERE contact_.Id=@p0; @p0 = '1'
NHibernate: INSERT INTO Customers (AccountNumber, DateCreated,
DateModified, LastModifiedBy) VALUES (@p0, @p1, @p2, @p3); select
SCOPE_IDENTITY(); @p0 = '', @p1 = '20/04/2009 19:45:34', @p2 =
'20/04/2009 19:45:34', @p3 = ''
NHibernate: INSERT INTO Individuals (ContactID, CustomerId) VALUES
(@p0, @p1); @p0 = '1', @p1 = '1'
NHibernate: SELECT individual_1_.Version as Version2_ FROM Individuals
individual_ inner join Customers individual_1_ on
individual_.CustomerId=individual_1_.Id WHERE
individual_.CustomerId=@p0; @p0 = '1'
NHibernate: UPDATE Contacts SET Version = @p0 WHERE Id = @p1 AND
Version = @p2; @p0 = 'System.Byte[]', @p1 = '1', @p2 = 'System.Byte[]'

System.Data.SqlClient.SqlException: Cannot update a timestamp column.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception,
Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException
exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning
(TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,
SqlCommand cmdHandler, SqlDataReader dataStream,
BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject
stateObj)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader
ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds
(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean
returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery
(DbAsyncResult result, String methodName, Boolean sendToPipe)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd)
in c:\CSharp\NH\nhibernate\src\NHibernate\AdoNet\AbstractBatcher.cs:
line 203
at NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object
id, Object[] fields, Object[] oldFields, Object rowId, Boolean[]
includeProperty, Int32 j, Object oldVersion, Object obj,
SqlCommandInfo sql, ISessionImplementor session) in c:\CSharp\NH
\nhibernate\src\NHibernate\Persister\Entity
\AbstractEntityPersister.cs: line 2713
NHibernate.Exceptions.GenericADOException: could not update:
[Core.Domain.Entities.Contact#1][SQL: UPDATE Contacts SET Version =
@p0 WHERE Id = @p1 AND Version = @p2]

任何想法为什么NHibernate试图更新联系人的版本列,即使它没有为地址?

地址没有我假设的版本列。

我想知道你在哪里有sql-type。 为什么不这样呢?

   <version name="Version" type="Timestamp" generated="always" unsaved-value="null">
     <column name="Version" not-null="false" />
   </version>

当然,您需要在实体中使用DateTime。

我发现在类上使用dynamic-insert =“true”会导致此问题。 我成功使用以下映射:

...
    <class name="Contact" table="Contact">
        <id name="ID" column="ID" type="int">
            <generator class="identity" />
        </id>
        <version name="Version" generated="always" unsaved-value="null" type="BinaryBlob"/>
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM