2012-10-01 26 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; } } 
}