2010-07-30 48 views
21

Tìm kiếm nhiều danh sách NHibernate khác nhau và chưa đưa ra câu trả lời dứt khoát. SQL2008 dialect dường như không hỗ trợ loại dữ liệu Phân cấp - chỉ các loại ngày và giờ mới.Hỗ trợ HierarchyID SQL 2008 trong NHibernate

Có ai có triển khai tốt hay giải pháp hiệu quả không? Tôi thực sự muốn tận dụng HierarchyID trong một ứng dụng mới của tôi. Hỗ trợ cho loại dữ liệu thú vị và mạnh mẽ này là thiếu trong các công cụ riêng của MS vì vậy tôi không bị sốc rằng NHibernate không có hỗ trợ.

someapproaches trên mạng mà tôi chưa được khắc phục. Tự hỏi liệu có ai có kinh nghiệm về những gì có hiệu quả hay không, những gì diễn đạt hơn, v.v.

Tiết lộ đầy đủ: Tôi đang làm việc với Castle ActiveRecord nhưng điều này có vẻ như vấn đề về NHibernate.

Trả lời

9

Tuyên bố từ chối trách nhiệm: Im không phải là chuyên gia NHibernate, tuy nhiên, chúng tôi đang sử dụng nó với Lưu loát trong dự án sắp tới sử dụng SQL Server 2008 R2 và ID phân cấp. Mã dưới đây là những gì chúng tôi đang sử dụng hiện tại trên môi trường dev của chúng tôi và không được kiểm tra đầy đủ/tinh tế. Tôi đã sao chép phần lớn mã từ nơi khác (xin lỗi tôi đã mất liên kết!)

Bạn cần tạo Kiểu do người dùng xác định và sau đó sử dụng nó trong ánh xạ của bạn. Ánh xạ bên dưới là thông thạo, Im không biết cách sử dụng nó bằng ActiveRecord nhưng tôi đoán nó sẽ giống như vậy!

User Defined Loại

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; } 
    } 
} 
} 

thạo Mapping

Map(e => e.YourSqlHierarchyIdProperty) 
    .Column("YourSqlHierarchyIdFieldName") 
    .CustomType<SqlHierarchyIdUserType>(); 

Đọc bài đăng này:

Castle ActiveRecord: Map to IUserType wihtin Class in C#

ActiveR ecord sử dụng thuộc tính [Property] để ánh xạ các kiểu do người dùng định nghĩa. Vì vậy, đối với bạn, nó sẽ trông giống như sau:

public class YourDataObject { 
    [Property(ColumnType="YourNamespace.SqlHierarchyIdUserType, YourNamespace") 
    public virtual SqlHierarchyId YourSqlHierarchyIdProperty; 
} 

Hy vọng điều đó sẽ hữu ích!

+0

Cảm ơn câu trả lời Needles.Dự án này đã được một thời gian trước cho tôi vì vậy tôi không thể nói nếu điều này sẽ làm việc (mặc dù trong nháy mắt nó có vẻ âm thanh). Nếu ai đó kêu trong đó nó hoạt động tôi sẽ đánh dấu nó như là câu trả lời. – JasonCoder

10

Tôi đã cung cấp cho Kim 'câu trả lời chạy thử nghiệm. Đó là một câu trả lời rất hay nhưng có một số thay đổi cần thiết để làm cho nó hoạt động (ít nhất là trong .NET 4). Dưới đây là những gì tôi đã đưa ra cho dự án của tôi:

Cập nhật: mã sau có thể tải xuống tại GitHub và sẽ được cập nhật ở đó. 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 
    } 
} 

Mapping

<?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> 

Object với 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 
    } 
} 
Các vấn đề liên quan