2013-02-03 34 views
0

有沒有辦法將創建(INSERT)行爲與SELECT行爲分開。在NHibernate上實現不同的SELECT和INSERT行爲IUserType

比方說,我有一列的數據庫將返回一個字符串看起來像這樣

Predecessors = "1,3,4,5" 

在我的應用我想用這個字符串像一個int數組通過實施IUserType

public interface IIntArray 
{ 
    int[] Items { get; set; } 
} 

public class IntArray : IIntArray 
{ 
    public int[] Items { get; set; } 

    public IntArray(string item) 
    { 
     if(string.IsNullOrEmpty(item)) 
      return; 

     Items = System.Array.ConvertAll<string, int>(item.Split(new[] {','}), int.Parse); 

     // for older .net versions use the code below 
     // Items = Array.ConvertAll<string, int>(item.ToString().Split(new[] { ',' }), delegate(string str) { return int.Parse(str); }); 
    } 
} 

public class IntArrayType : IUserType 
{ 
    #region Implementation of IUserType 

    /// <summary> 
    /// Compare two instances of the class mapped by this type for persistent "equality" 
    /// ie. equality of persistent state 
    /// </summary> 
    /// <param name="x"></param> 
    /// <param name="y"></param> 
    /// <returns></returns> 
    public new bool Equals(object x, object y) 
    { 
     if (x == null && y == null) return true; 
     if (x == null || y == null) return false; 
     return x.GetType() == y.GetType(); 
    } 

    /// <summary> 
    /// Get a hashcode for the instance, consistent with persistence "equality" 
    /// </summary> 
    public int GetHashCode(object x) 
    { 
     return x.GetHashCode(); 
    } 

    /// <summary> 
    /// Retrieve an instance of the mapped class from a resultset. 
    /// Implementors should handle possibility of null values. 
    /// </summary> 
    /// <param name="rs">a IDataReader</param> 
    /// <param name="names">column names</param> 
    /// <param name="owner">the containing entity</param> 
    /// <returns></returns> 
    /// <exception cref="HibernateException">HibernateException</exception> 
    public object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
     var value = NHibernateUtil.String.NullSafeGet(rs, names[0]); 

     if (value == null || (string.IsNullOrEmpty(value.ToString()))) 
     { 
      return null; 
     } 

     return new IntArray(value.ToString()); 
    } 

    /// <summary> 
    /// Write an instance of the mapped class to a prepared statement. 
    /// Implementors should handle possibility of null values. 
    /// A multi-column type should be written to parameters starting from index. 
    /// </summary> 
    /// <param name="cmd">a IDbCommand</param> 
    /// <param name="value">the object to write</param> 
    /// <param name="index">command parameter index</param> 
    /// <exception cref="HibernateException">HibernateException</exception> 
    public void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
     if (value == null) 
     { 
      ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value; 
     } 
     else 
     { 
      var state = (IIntArray)value; 
      ((IDataParameter)cmd.Parameters[index]).Value = state.GetType().Name; 
     } 
    } 

    /// <summary> 
    /// Return a deep copy of the persistent state, stopping at entities and at collections. 
    /// </summary> 
    /// <param name="value">generally a collection element or entity field</param> 
    /// <returns>a copy</returns> 
    public object DeepCopy(object value) 
    { 
     return value; 
    } 

    /// <summary> 
    /// During merge, replace the existing (<paramref name="target" />) value in the entity 
    /// we are merging to with a new (<paramref name="original" />) value from the detached 
    /// entity we are merging. For immutable objects, or null values, it is safe to simply 
    /// return the first parameter. For mutable objects, it is safe to return a copy of the 
    /// first parameter. For objects with component values, it might make sense to 
    /// recursively replace component values. 
    /// </summary> 
    /// <param name="original">the value from the detached entity being merged</param> 
    /// <param name="target">the value in the managed entity</param> 
    /// <param name="owner">the managed entity</param> 
    /// <returns>the value to be merged</returns> 
    public object Replace(object original, object target, object owner) 
    { 
     return original; 
    } 

    /// <summary> 
    /// Reconstruct an object from the cacheable representation. At the very least this 
    /// method should perform a deep copy if the type is mutable. (optional operation) 
    /// </summary> 
    /// <param name="cached">the object to be cached</param> 
    /// <param name="owner">the owner of the cached object</param> 
    /// <returns>a reconstructed object from the cachable representation</returns> 
    public object Assemble(object cached, object owner) 
    { 
     return cached; 
    } 

    /// <summary> 
    /// Transform the object into its cacheable representation. At the very least this 
    /// method should perform a deep copy if the type is mutable. That may not be enough 
    /// for some implementations, however; for example, associations must be cached as 
    /// identifier values. (optional operation) 
    /// </summary> 
    /// <param name="value">the object to be cached</param> 
    /// <returns>a cacheable representation of the object</returns> 
    public object Disassemble(object value) 
    { 
     return value; 
    } 

    /// <summary> 
    /// The SQL types for the columns mapped by this type. 
    /// </summary> 
    public SqlType[] SqlTypes { get { return new[] { NHibernateUtil.String.SqlType }; } } 

    /// <summary> 
    /// The type returned by <c>NullSafeGet()</c> 
    /// </summary> 
    public Type ReturnedType { get { return typeof(IntArray); } } 

    /// <summary> 
    /// Are objects of this type mutable? 
    /// </summary> 
    public bool IsMutable { get { return false; } } 

    #endregion 
} 

在我NHibernate的I類映射到物業這樣

public virtual IntArray Predecessors { get; set; } 

和HBM映射

<property name="Predecessors" type="Example.IntArrayType, Example" /> 

的IntArray類完成數據的讀取,試圖把東西回來,這並不工作時,當它的工作。我想要做的就是以某種方式迫使IntArray屬性呈現IntArray.Items的值,以逗號分隔字符串

string magic = string.Join(",", Predecessors.Items); 

感謝

+0

我正在考慮使用NHibernate IInterceptors,但實現相當粗糙。 –

回答

0

像這樣的東西應該做的伎倆

public void NullSafeSet(IDbCommand cmd, object value, int index) 
{ 
    var ints = value as IntArray; 
    if(ints != null && ints.Items != null) 
    { 
     NHibernate.NHibernateUtil.StringClob.NullSafeSet(cmd, string.Join(", ", ints.Items), index); 
    } 
} 
相關問題