我正在试图弄清楚如何在流畅的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>
生成映射。有人可以提供一些提示吗?
答案 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 };
}
}
}