两张以上桌子上的NHibernate是否损坏?
鉴于此:两张以上桌子上的NHibernate是否损坏?,nhibernate,entity-framework,Nhibernate,Entity Framework,鉴于此: namespace TheEntities { [DataContract(IsReference=true)] public class Question { [DataMember] public virtual int QuestionId { get; set; } [DataMember] public virtual string Text { get; set; } [DataMember]
namespace TheEntities
{
[DataContract(IsReference=true)]
public class Question
{
[DataMember] public virtual int QuestionId { get; set; }
[DataMember] public virtual string Text { get; set; }
[DataMember] public virtual string Poster { get; set; }
[DataMember] public virtual IList<QuestionComment> Comments { get; set; }
[DataMember] public virtual IList<Answer> Answers{ get; set; }
[DataMember] public virtual byte[] RowVersion { get; set; }
}
[DataContract]
public class QuestionComment
{
[DataMember] public virtual Question Question { get; set; }
[DataMember] public virtual int QuestionCommentId { get; set; }
[DataMember] public virtual string Text { get; set; }
[DataMember] public virtual string Poster { get; set; }
}
[DataContract(IsReference = true)]
public class Answer
{
[DataMember] public virtual Question Question { get; set; }
[DataMember] public virtual int AnswerId { get; set; }
[DataMember] public virtual string Text { get; set; }
[DataMember] public virtual string Poster { get; set; }
[DataMember] public virtual IList<AnswerComment> Comments { get; set; }
}
[DataContract]
public class AnswerComment
{
[DataMember] public virtual Answer Answer { get; set; }
[DataMember] public virtual int AnswerCommentId { get; set; }
[DataMember] public virtual string Text { get; set; }
[DataMember] public virtual string Poster { get; set; }
}
}
这也会生成重复对象(仅两层深,但使用三种关系):
这不会产生重复的对象,但是急切加载只针对两个层次和两个关系,即从问题到答案。对于要提问的注释和要回答的注释,它们在单独的查询中执行
query = query
.FetchMany(x => x.Answers);
如果NHibernate只能对两个级别的FetchMany做好它的工作,那么为什么还要费心创建FetchMany(用于三个级别,但有错误,有重复的对象)?事实上,即使FetchMany也没用如果你想在三个关系上使用它,它也会产生重复的对象
NHibernate团队会因为无法正常工作而费心删除许多吗
我的映射没有错误,当我删除抓取策略时,一切正常(即不产生重复对象)。尝试:
query.QueryOptions.RegisterCustomAction(c => c.SetResultTransformer(new DistinctRootEntityResultTransformer()));
要获得独特的结果,请执行以下操作: 对于Linq:
.Distinct()
询问者
.TrasformUsing(Transformers.DistinctRootentity)
标准
.SetResulttransformer(Transformers.DistinctRootentity)
编辑:这实际上是NH的一个缺点,它将发布笛卡尔乘积,但这可以改进
repo.All.Where(y => y.QuestionId == id)
.FetchMany(x => x.Answers)
.ThenFetchMany(x => x.Comments)
.Future()
query = repo.All.Where(y => y.QuestionId == id)
.FetchMany(x => x.Comments)
var result = query.AsEnumerable().Single();
看
它看起来有点奇怪,但应该做你可以做你想做的事-append
.TrasformUsing(Transformers.distinctroventy)
。这当然很烦人。这只在QueryOver上可用,但我使用的是NH的Linq(IQueryable)。NH Linq扩展方法与.TransformUsing
等效于什么?这是因为实体框架使用一些联合创建查询,而NHibernate执行连接。连接产生笛卡尔积,从而产生重复实体。在这种情况下,EF的策略更好,因为它允许在一个查询中获得更多信息。这仅在NH2.0 Linq上可用。在NH3.0上,Linq丢失了。在NH3.0中,Linq没有丢失。它有自己的LINQ提供商。您可以通过.Query访问它。您可以在QueryOver上使用变压器。但是,在一个查询中不应该多次使用FetchMany。是的,我知道,NHibernate 3支持LINQ,它可以通过.query访问,在LINQ 2上,它在.LINQ上。事实上,自从我开始使用NH以来,我只通过HQL和Linq进行查询(现在专门处理这个问题,不喜欢HQL magic string)。我只是将.Query
放在我的存储库界面的All
属性中。我的意思是NH3.0LINQ上的,它丢失了
,我只是忘了在单词Linq和它之间加一个逗号;-)它是:QueryOptions.RegisterCustomAction
.TrasformUsing(Transformers.DistinctRootentity)
.SetResulttransformer(Transformers.DistinctRootentity)
repo.All.Where(y => y.QuestionId == id)
.FetchMany(x => x.Answers)
.ThenFetchMany(x => x.Comments)
.Future()
query = repo.All.Where(y => y.QuestionId == id)
.FetchMany(x => x.Comments)
var result = query.AsEnumerable().Single();