Fluent Nhibernate 多级参考
Fluent Nhibernate Multi-Level reference
我有一个三代 class 结构,我正尝试使用 Fluent Nhibernate 对其进行 ORM 化。总结 classes 它们看起来是这样的...
public class Highest{
public virtual Guid Id{
get;
set;
}
public virtual IList<Medium> Children{
get;
set;
}
}
public class Medium{
public virtual int Index{
get;
set;
}
public virtual Highest Parent{
get;
set;
}
public virtual IList<Lowest> Children{
get;
set;
}
}
public class Lowest{
public virtual MyEnum LowType{
get;
set;
}
public virtual Medium Parent{
get;
set;
}
}
我已经尝试了很多次尝试使用简单的 Id 为最高级别和复合 Id 为中级和最低级别创建适当的地图。但是我所有的策略都没有为从最低到中等创建一个 compositeid,因为(我假设)它反过来使用从自身到最高的 CompositeId。
问题!
应该如何 设计地图,以便我确定当我加载最高 class 时,所有中等和较低的关系也将被创建,包括 Parent/Children关系。
谢谢!
您请求的映射
public class HighestMap : ClassMap<Highest>
{
public HighestMap()
{
Id(x => x.Id).GeneratedBy.GuidComb();
HasMany(x => x.Children)
.KeyColumn("parent_id");
}
}
public class MediumMap : ClassMap<Medium>
{
public MediumMap()
{
CompositeId()
.KeyReference(x => x.Parent, "parent_id")
.KeyProperty(x => x.Index, "indexColumn");
HasMany(x => x.Children)
.KeyColumns.Add("medium_id", "indexColumn")
.Component(c =>
{
c.ParentReference(x => x.Parent);
c.Map(x => x.LowType);
});
}
}
但是您说过要一次加载所有内容,那么为了性能牺牲可查询性可能是值得的。以下代码会将 Medium.Children 集合作为字符串保存在数据库中,并且只能用相等和不相等的 session.Query<Medium>().Where(x => x.Children == myCollection);
进行查询
public class Medium
{
public virtual Highest Parent { get; set; }
public virtual ICollection<MyEnum> Children { get; set; }
}
public class HighestMap : ClassMap<Highest>
{
public HighestMap()
{
Id(x => x.Id).GeneratedBy.GuidComb();
HasMany(x => x.Children)
.KeyColumn("parent_id")
.AsList(i => i.Column("indexColumn"))
.Component(c =>
{
c.ParentReference(x => x.Parent);
// remove Index property and use Highest.Children.IndexOf(medium)
c.Map(x => x.Children).CustomType<EnumCollectionAsStringUserType<MyEnum>>();
});
}
}
[Serializable]
public class EnumCollectionAsStringUserType<TEnum> : IUserType
{
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
var value = (string)NHibernateUtil.String.Get(rs, names[0]);
if (string.IsNullOrEmpty(value))
return new List<TEnum>();
return value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(Parse).ToList();
}
private static TEnum Parse(string arg)
{
return (TEnum)Enum.Parse(typeof(TEnum), arg);
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
var collection = (IEnumerable<TEnum>)value;
NHibernateUtil.String.Set(cmd, string.Join(",", collection), index);
}
public Type ReturnedType { get { return typeof(ICollection<TEnum>); } }
public SqlType[] SqlTypes { get { return new[] { SqlTypeFactory.GetString(255) }; } }
public object DeepCopy(object value)
{
return new List<TEnum>((IEnumerable<TEnum>)value);
}
bool IUserType.Equals(object x, object y)
{
return ((IEnumerable<TEnum>)x).SequenceEqual((IEnumerable<TEnum>)y);
}
int IUserType.GetHashCode(object x)
{
return ((IEnumerable<TEnum>)x).Aggregate(0, (a, v) => a << 8 + v.GetHashCode());
}
public object Assemble(object cached, object owner)
{
return DeepCopy(cached);
}
public object Disassemble(object value)
{
return DeepCopy(value);
}
public bool IsMutable { get { return true; } }
public object Replace(object original, object target, object owner)
{
return original;
}
}
我有一个三代 class 结构,我正尝试使用 Fluent Nhibernate 对其进行 ORM 化。总结 classes 它们看起来是这样的...
public class Highest{
public virtual Guid Id{
get;
set;
}
public virtual IList<Medium> Children{
get;
set;
}
}
public class Medium{
public virtual int Index{
get;
set;
}
public virtual Highest Parent{
get;
set;
}
public virtual IList<Lowest> Children{
get;
set;
}
}
public class Lowest{
public virtual MyEnum LowType{
get;
set;
}
public virtual Medium Parent{
get;
set;
}
}
我已经尝试了很多次尝试使用简单的 Id 为最高级别和复合 Id 为中级和最低级别创建适当的地图。但是我所有的策略都没有为从最低到中等创建一个 compositeid,因为(我假设)它反过来使用从自身到最高的 CompositeId。
问题! 应该如何 设计地图,以便我确定当我加载最高 class 时,所有中等和较低的关系也将被创建,包括 Parent/Children关系。
谢谢!
您请求的映射
public class HighestMap : ClassMap<Highest>
{
public HighestMap()
{
Id(x => x.Id).GeneratedBy.GuidComb();
HasMany(x => x.Children)
.KeyColumn("parent_id");
}
}
public class MediumMap : ClassMap<Medium>
{
public MediumMap()
{
CompositeId()
.KeyReference(x => x.Parent, "parent_id")
.KeyProperty(x => x.Index, "indexColumn");
HasMany(x => x.Children)
.KeyColumns.Add("medium_id", "indexColumn")
.Component(c =>
{
c.ParentReference(x => x.Parent);
c.Map(x => x.LowType);
});
}
}
但是您说过要一次加载所有内容,那么为了性能牺牲可查询性可能是值得的。以下代码会将 Medium.Children 集合作为字符串保存在数据库中,并且只能用相等和不相等的 session.Query<Medium>().Where(x => x.Children == myCollection);
public class Medium
{
public virtual Highest Parent { get; set; }
public virtual ICollection<MyEnum> Children { get; set; }
}
public class HighestMap : ClassMap<Highest>
{
public HighestMap()
{
Id(x => x.Id).GeneratedBy.GuidComb();
HasMany(x => x.Children)
.KeyColumn("parent_id")
.AsList(i => i.Column("indexColumn"))
.Component(c =>
{
c.ParentReference(x => x.Parent);
// remove Index property and use Highest.Children.IndexOf(medium)
c.Map(x => x.Children).CustomType<EnumCollectionAsStringUserType<MyEnum>>();
});
}
}
[Serializable]
public class EnumCollectionAsStringUserType<TEnum> : IUserType
{
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
var value = (string)NHibernateUtil.String.Get(rs, names[0]);
if (string.IsNullOrEmpty(value))
return new List<TEnum>();
return value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(Parse).ToList();
}
private static TEnum Parse(string arg)
{
return (TEnum)Enum.Parse(typeof(TEnum), arg);
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
var collection = (IEnumerable<TEnum>)value;
NHibernateUtil.String.Set(cmd, string.Join(",", collection), index);
}
public Type ReturnedType { get { return typeof(ICollection<TEnum>); } }
public SqlType[] SqlTypes { get { return new[] { SqlTypeFactory.GetString(255) }; } }
public object DeepCopy(object value)
{
return new List<TEnum>((IEnumerable<TEnum>)value);
}
bool IUserType.Equals(object x, object y)
{
return ((IEnumerable<TEnum>)x).SequenceEqual((IEnumerable<TEnum>)y);
}
int IUserType.GetHashCode(object x)
{
return ((IEnumerable<TEnum>)x).Aggregate(0, (a, v) => a << 8 + v.GetHashCode());
}
public object Assemble(object cached, object owner)
{
return DeepCopy(cached);
}
public object Disassemble(object value)
{
return DeepCopy(value);
}
public bool IsMutable { get { return true; } }
public object Replace(object original, object target, object owner)
{
return original;
}
}