搜索了各种NHibernate列表,但没有得到明确的答案。SQL2008 dialect似乎不支持HierarchyID数据类型--只支持新的日期和时间类型。
有没有人有一个好的实现或有效的解决办法?我真的很想在我的一个新应用中利用HierarchyID。MS自己的工具非常缺乏对这种有趣而强大的数据类型的支持,所以我对NHibernate没有支持并不感到惊讶。
还有一些我还没有深入研究的some approaches。想知道有没有人有经验知道什么是有效的,什么是更好的性能,等等。
全面披露:我正在使用Castle ActiveRecord,但这似乎是一个NHibernate问题。
发布于 2012-05-29 15:37:37
免责声明:我不是NHibernate专家,但是,我们在即将到来的使用SQL Server2008 R2和层次结构ID的项目中通过Fluent使用它。下面的代码是我们目前在开发环境中使用的代码,并没有经过充分的测试/改进。我从别处复制了大部分代码(抱歉,我丢失了链接!)
您需要创建一个用户定义类型,然后在您的映射中使用它。下面的映射很流畅,我不知道如何使用ActiveRecord来做,但我猜它应该是相似的!
用户定义类型
namespace YourNamespace {
public class SqlHierarchyIdUserType : IUserType {
public bool Equals(object x, object y) {
if(ReferenceEquals(x, y))
return true;
if(x == null || y == null)
return false;
return x.Equals(y);
}
public int GetHashCode(object x) {
return x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner) {
object prop1 = NHibernateUtil.String.NullSafeGet(rs, names[0]);
if(prop1 == null)
return null;
return SqlHierarchyId.Parse(new SqlString(prop1.ToString()));
}
public void NullSafeSet(IDbCommand cmd, object value, int index) {
if(value == null) {
((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
} else {
if(value is SqlHierarchyId) {
SqlHierarchyId hId = (SqlHierarchyId)value;
((IDataParameter)cmd.Parameters[index]).Value = hId.ToString();
}
}
}
public object DeepCopy(object value) {
if(value == null)
return null;
var sourceTarget = (SqlHierarchyId)value;
SqlHierarchyId copy = SqlHierarchyId.Parse(sourceTarget.ToString());
return copy;
}
public object Replace(object original, object target, object owner) {
return DeepCopy(original);
}
public object Assemble(object cached, object owner) {
return DeepCopy(cached);
}
public object Disassemble(object value) {
return DeepCopy(value);
}
public SqlType[] SqlTypes {
get { return new[] { NHibernateUtil.String.SqlType }; }
}
public Type ReturnedType {
get { return typeof(SqlHierarchyId); }
}
public bool IsMutable {
get { return true; }
}
}
}Fluent映射
Map(e => e.YourSqlHierarchyIdProperty)
.Column("YourSqlHierarchyIdFieldName")
.CustomType<SqlHierarchyIdUserType>();阅读这篇文章:
Castle ActiveRecord: Map to IUserType wihtin Class in C#
ActiveRecord使用Property属性来映射用户定义的类型。所以对于你来说,它看起来像这样:
public class YourDataObject {
[Property(ColumnType="YourNamespace.SqlHierarchyIdUserType, YourNamespace")
public virtual SqlHierarchyId YourSqlHierarchyIdProperty;
}希望它能帮上忙!
发布于 2012-06-19 00:39:33
我已经对Needles的答案进行了测试。这是一个非常好的答案,但需要做一些修改才能让它发挥作用(至少在.NET 4中是这样)。这是我为我的项目想出的想法:
更新:以下代码可以从GitHub下载,并将在那里更新。NHiberntate.HierarchyId.UserType
SqlHierarchyId IUserType
namespace NHibernate.UserTypes
{
using SqlTypes;
using System;
using System.Data;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Types;
public class HierarchyId : IUserType
{
#region Properties
public SqlType[] SqlTypes
{
get { return new[] { NHibernateUtil.String.SqlType }; }
}
public Type ReturnedType
{
get { return typeof(SqlHierarchyId); }
}
public bool IsMutable
{
get { return true; }
}
#endregion Properties
#region Methods
new public bool Equals(object x, object y)
{
if (ReferenceEquals(x, y)) return true;
if (x == null || y == null) return false;
return x.Equals(y);
}
public int GetHashCode(object x)
{
return x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
object prop1 = NHibernateUtil.String.NullSafeGet(rs, names[0]);
if (prop1 == null) return null;
return SqlHierarchyId.Parse(new SqlString(prop1.ToString()));
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
if (value == null)
((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
else if (value is SqlHierarchyId)
((IDataParameter)cmd.Parameters[index]).Value = ((SqlHierarchyId)value).ToString();
}
public object DeepCopy(object value)
{
if (value == null) return null;
return SqlHierarchyId.Parse(((SqlHierarchyId)value).ToString());
}
public object Replace(object original, object target, object owner)
{
return DeepCopy(original);
}
public object Assemble(object cached, object owner)
{
return DeepCopy(cached);
}
public object Disassemble(object value)
{
return DeepCopy(value);
}
#endregion Methods
}
}映射
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DataLayer" namespace="NHibernate.Map">
<class name="NHibernate.Map.OrganizationUnit, DataLayer" table="`orgunit`">
<property name="HierarchyId" column="`ou_hid`" type="NHibernate.UserTypes.HierarchyId, DataLayer" />
...
</class>
</hibernate-mapping>使用HierarchyId的对象
namespace NHibernate.Map
{
using Microsoft.SqlServer.Types;
public class OrganizationUnit
{
#region Fields
private SqlHierarchyId _hierarchyId;
...
#endregion Fields
#region Properties
public virtual SqlHierarchyId HierarchyId
{
get { return _hierarchyId; }
set { _hierarchyId = value; }
}
...
#endregion Properties
}
}https://stackoverflow.com/questions/3374904
复制相似问题