2012-10-01 64 views
0

如果我不映射Color但映射具有Color屬性的對象,則FluentNHibernate將它成功映射到varbinary(max)。但是,這是非常低效的,因爲Color實際上只是由4個字節組成,而我非常希望在不使用新類型代理它的情況下改進它。映射System.Drawing.Color

在內部內Color它是由四個屬性,

  1. long value(垂下到int代表ARGB)
  2. short state,表示如果這是一個公知的&有效的顏色
  3. string name,顏色的名稱,如果知道。
  4. short knownColor,來表示其已知的顏色是

所以我試圖映射此如下。

public ColorMapping() 
{ 
    CompositeId() 
     .KeyProperty(c => Reveal.Member<Color, long>("value")) 
     .KeyProperty(c => Reveal.Member<Color, short>("state")) 
     .KeyProperty(c => Reveal.Member<Color, string>("name")) 
     .KeyProperty(c => Reveal.Member<Color, short>("knownColor")); 
} 

然而,在使用我得到下面的異常,

類初始化方法DataContextTest.ClassInitialise拋出 例外。 FluentNHibernate.Cfg.FluentConfigurationException: FluentNHibernate.Cfg.FluentConfigurationException:在創建SessionFactory時使用了一個無效的配置或者配置不完整。 檢查PotentialReasons集合和InnerException以獲取更多詳細信息。

---> FluentNHibernate.Cfg.FluentConfigurationException:創建SessionFactory時使用了一個無效的或不完整的配置。 檢查PotentialReasons集合和InnerException以獲取更多詳細信息。

---> NHibernate.MappingException:無法編譯映射 文件:(XmlDocument的)---> NHibernate.MappingException:無法 確定類型: System.Linq.Expressions.Expression 1[[System.Func 2〔〔 System.Drawing.Color, System.Drawing,Version = 4.0.0.0,Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a],[System.Int64,mscorlib, Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]] , mscorlib,Version = 4.0.0.0,Culture = neutral, PublicKeyToken = b77a5c561934e089]],System.Core,Version = 4.0.0.0, Culture = neutral,PublicKeyToken = b77a5c561934e089,對於列: NHibernate.Mapping.Column(Member)。

我是濫用Reveal?如果是這樣,我該如何使用它?

+0

PotentialReasons的內容是什麼?您可能需要加載[組件的第一(http://stackoverflow.com/questions/1520758/fluent-nhibernate-mapping-entities-from-multiple-assemblies)。 – Sebazzz

+0

@Sebazzz'PotentialReasons Count = 0' –

回答

1

我將它映射爲用戶類型它轉換來回

// in mapping 
Map(x => x.Color).Column("ColorARGB").CustomType<ColorUserType>(); 

[Serializable] 
class ColorUserType : IUserType 
{ 
    public object Assemble(object cached, object owner) 
    { 
     return DeepCopy(cached); 
    } 

    public object DeepCopy(object value) 
    { 
     return value; 
    } 

    public object Disassemble(object value) 
    { 
     return DeepCopy(value); 
    } 

    bool IUserType.Equals(object x, object y) 
    { 
     var colorX = x as Color; 
     var colorY = y as Color; 
     return colorX == null ? colorY = null : colorX.ToArgb() == colorY.ToArgb(); 
    } 

    public virtual int GetHashCode(object x) 
    { 
     var colorX = (Color)x; 
     return (colorX != null) ? colorX.ToArgb() : 0; 
    } 

    public bool IsMutable { get { return false; } } 

    public object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
     return Color.FromArgb((int)NHibernateUtil.Int32.Get(rs, names[0])); 
    } 

    public void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
     NHibernateUtil.Int32.Set(cmd, ((Color)value).ToArgb(), index); 
    } 

    public object Replace(object original, object target, object owner) 
    { 
     return original; 
    } 

    public Type ReturnedType { get { return typeof(Color); } } 

    public SqlType[] SqlTypes { get { return new []{ SqlTypeFactory.Int32 }; } } 
} 
+0

它沒有保存足夠的信息。 FromRGB從ARGB組件創建一個Color對象。生成的對象與已知的顏色不同。例如'Assert.AreEqual(Color.Blue,Color.FromArgb(-16776961))'會產生一個'Exception'。 (該值是ARGB 255,0,0,255) –

+0

則只需更改equals方法使用ToArgb()值是否相等 – Firo

+0

有沒有辦法有一個IUserType創建兩列?一個用於ARGB值,一個用於KnownColor?或者我是否需要將這兩個值轉換爲Int64並進行切換? –

0

我跟到底的ICompositeUserType去了。 代碼如下,

public class ColorType : ICompositeUserType 
{ 
    /// <summary> 
    /// Get the value of a property 
    /// </summary> 
    /// <param name="component">an instance of class mapped by this "type"</param> 
    /// <param name="property"/> 
    /// <returns> 
    /// the property value 
    /// </returns> 
    public object GetPropertyValue(object component, int property) 
    { 
     var color = (Color) component; 
     if (property == 0) 
     { 
      return color.ToArgb(); 
     } 

     return (int) color.ToKnownColor(); 
    } 

    /// <summary> 
    /// Set the value of a property 
    /// </summary> 
    /// <param name="component">an instance of class mapped by this "type"</param> 
    /// <param name="property"/> 
    /// <param name="value">the value to set</param> 
    public void SetPropertyValue(object component, int property, object value) 
    { 
     throw new InvalidOperationException("Color is immutable"); 
    } 

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

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

    /// <summary> 
    /// Retrieve an instance of the mapped class from a IDataReader. Implementors 
    ///    should handle possibility of null values. 
    /// </summary> 
    /// <param name="dr">IDataReader</param> 
    /// <param name="names">the column names</param> 
    /// <param name="session"/> 
    /// <param name="owner">the containing entity</param> 
    /// <returns/> 
    public object NullSafeGet(IDataReader dr, string[] names, 
     ISessionImplementor session, object owner) 
    { 
     var argb = (int?) NHibernateUtil.Int32.NullSafeGet(dr, names[0]); 
     var knownColor = (int?) NHibernateUtil.Int32.NullSafeGet(dr, names[1]); 
     return knownColor != null 
      ? Color.FromKnownColor((KnownColor) knownColor.Value) 
      : Color.FromArgb(argb.Value); 
    } 

    /// <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. 
    ///    If a property is not settable, skip it and don't increment the index. 
    /// </summary> 
    /// <param name="cmd"/> 
    /// <param name="value"/> 
    /// <param name="index"/> 
    /// <param name="settable"/> 
    /// <param name="session"/> 
    public void NullSafeSet(IDbCommand cmd, object value, int index, 
     bool[] settable, ISessionImplementor session) 
    { 
     var color = (Color) value; 
     if (color.IsKnownColor) 
     { 
      ((IDataParameter) cmd.Parameters[index]).Value = DBNull.Value; 
      ((IDataParameter) cmd.Parameters[index + 1]).Value = (int) color.ToKnownColor(); 
     } 
     else 
     { 
      ((IDataParameter) cmd.Parameters[index]).Value = color.ToArgb(); 
      ((IDataParameter) cmd.Parameters[index + 1]).Value = DBNull.Value; 
     } 
    } 

    /// <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/> 
    public object DeepCopy(object value) 
    { 
     return value; 
    } 

    /// <summary> 
    /// Transform the object into its cacheable representation. 
    ///    At the very least this method should perform a deep copy. 
    ///    That may not be enough for some implementations, 
    ///    method should perform a deep copy. 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> 
    /// <param name="session"/> 
    /// <returns/> 
    public object Disassemble(object value, ISessionImplementor session) 
    { 
     return value; 
    } 

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

    /// <summary> 
    /// During merge, replace the existing (target) value in the entity we are merging to 
    ///    with a new (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. However, since 
    ///    composite user types often define component values, it might make sense to recursively 
    ///    replace component values in the target object. 
    /// </summary> 
    public object Replace(object original, object target, ISessionImplementor session, object owner) 
    { 
     return original; 
    } 

    /// <summary> 
    /// Get the "property names" that may be used in a query. 
    /// </summary> 
    public string[] PropertyNames { get { return new[] {"Argb", "KnownColor"}; } } 

    /// <summary> 
    /// Get the corresponding "property types" 
    /// </summary> 
    public IType[] PropertyTypes 
    { 
     get 
     { 
      return new IType[] 
        { 
         NHibernateUtil.Int32, NHibernateUtil.Int32 
        }; 
     } 
    } 

    /// <summary> 
    /// The class returned by NullSafeGet(). 
    /// </summary> 
    public Type ReturnedClass { get { return typeof (Color); } } 

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