有没有办法将 Create (INSERT) 行为与 SELECT 行为分开。
假设我有一个数据库,其中有一列将返回一个如下所示的字符串
Predecessors = "1,3,4,5"
在我的应用程序中,我想通过实现 IUserType 来像 int 数组一样使用这个字符串
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 类中,我映射到这样的属性
public virtual IntArray Predecessors { get; set; }
和 hbm 映射
<property name="Predecessors" type="Example.IntArrayType, Example" />
IntArray 类在读取数据时可以完成工作,但是在尝试放回某些东西时,这不起作用。我想做的是以某种方式强制 IntArray 属性将 IntArray.Items 的值呈现为逗号分隔的字符串
string magic = string.Join(",", Predecessors.Items);
谢谢