用于映射IDictionary <someentity,int =“”>?</someentity,>的流畅代码

时间:2009-09-01 07:11:20

标签: .net fluent-nhibernate

我正在试图弄清楚如何在流畅的1.0 RTM中映射IDictionary属性。

根据我的理解,这转化为三元关联。

示例:

class Bar
{
    public IDictionary<SomeEntity, int> Foo {get; set;}
}
然后

Bar.hbm.xml将包含:

<map name="Foo" table="BarFooTable">
    <key column="..."/>
    <index-many-to-many class="SomeEntity" column="SomeEntity_Id"/>
    <element column="Value" type="int"/>
</map>

我需要用流利的nhibernate来编写这个映射xml?

这里的关注点是密钥是实体类型,而值是值类型。 (编辑:至少,这似乎与其他各种示例和问题区别开来,这些示例和问题在stackoverflow或google组中浮现,这些都是值 - 值或密钥)

经过多次实验,我可以为IDictionary<SomeEntity,SomeEntity>(纯实体类型)生成映射:

HasManyToMany(x => x.Foo)
        .AsMap("Key")
        .AsTernaryAssociation("Key2", "Value")
        ; 

我还可以为IDictionary<int,int>(纯值类型)生成映射:

HasMany(x => x.Foo)
    .AsMap<int>("Key")
    .Element("Value")
    ;

我甚至可以通过某种方式为IDictionary<int, SomeValue)生成映射,尽管NHibernate都不接受。

但我无法弄清楚如何为我想要的IDictionary<SomeValue, int>生成映射。有人可以提供一些提示吗?

4 个答案:

答案 0 :(得分:2)

HasMany(x => x.Foo)
    .KeyColumn("BarId")
    .Element("IntValue")
    .AsMap<SomeEntity>("SomeEntityId")
    .AsTernaryAssociation("SomeEntityId");

答案 1 :(得分:1)

我遇到了同样的问题,并且不喜欢混合流利和hbm映射。您可以看到我的修正here

答案 2 :(得分:0)

看来我们遇到了同样的问题:

How to map this in Fluent.NHibernate

我刚刚使用了hbm.xml(由我的项目中的Fluent.Nhibernate生成)我修改了一点oufcourse。 如果你设置

 .Mappings(m =>
   {                                             
       m.FluentMappings.AddFromAssemblyOf<DomainClass>()
                       .ExportTo("Path");
       m.HbmMappings.AddFromAssemblyOf<DomainClass>();
   })

如果你同时拥有ClassMap和hbm.xml,那么hbm.xml应该覆盖ClassMap,所以你会很好,直到它被修复。

我的类也需要自然id,而Fluent.Nhibernate也不支持它,所以我别无选择,只能使用hbm.xml

答案 3 :(得分:0)

鉴于这些(简化)类:

class LetterTemplate
{
  IDictionary<State, FieldAccessOptionality> StateAccess {get; protected set;}
}

class State
{
}

enum FieldAccessOptionality
{
}

这对我有用。

(是的我知道该值是一个枚举,但原理与int相同)。

  HasManyToMany(x => x.StateAccess)
    .ParentKeyColumn("`letter_template`")
    .ChildKeyColumn("`state`")
    .AsMap<State>("`state`")
    .Element("`access`",
      p =>
        p.Type<IntEnumType<FieldAccessOptionality>>())
    .AsTernaryAssociation("`state`", "`access`")
    .Table("`letter_template_state_access`");

注意IntEnumType&lt;&gt;为NHibernate从枚举转换为int的类。 如果您正在映射int而不是枚举,则可以使用标准的NHibernate Int32Type IUserType。 该课程的完整列表如下:

public class IntEnumType<T> : IUserType where T : struct
{
  public object Assemble(object cached, object owner)
  {
    return cached;
  }

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

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

  public new bool Equals(object a, object b)
  {
    return Object.Equals(a, b);
  }

  public int GetHashCode(object x)
  {
    if (x == null)
      return 0;
    else
      return x.GetHashCode();
  }

  public bool IsMutable
  {
    get { return false; }
  }

  public object NullSafeGet(IDataReader rs, string[] names, object owner)
  {
    object result = NHibernateUtil.Int32.NullSafeGet(rs, names);
    if (result == null)
    {
      return null;
    }
    else
    {
      Type typ = Enum.GetUnderlyingType(typeof(T));
      result = Convert.ChangeType(result, typ);
      return Enum.ToObject(typeof(T), result);
    }
  }

  public void NullSafeSet(IDbCommand cmd, object value, int index)
  {
    if (value == null)
      ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
    else
      ((IDataParameter)cmd.Parameters[index]).Value = Convert.ChangeType(value, typeof(int));
  }

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

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

  public SqlType[] SqlTypes
  {
    get
    {
      SqlType type = new SqlType(DbType.Int32);
      return new SqlType[] { type };
    }
  }

}