我已经谷歌搜索了一段时间,现在试图理解nHibernate所以我可以自己解决它但是已经很短了。所以我来自Entity Framework v1,我们在其中编写一个select语句,如:
from query in context.Users.Include("Orders") where query.UserId == id select query;
或类似的地方,你会得到结果,说它是一个名为FoundUsers的局部变量,如果我想加载一个引用,就会编写一个Extension方法来加载引用,如果它没有被加载:
FoundUsers.Orders.LoadIfNotLoaded()
然后我们可以访问FoundUsers.Orders。有了这样说,你可以看到我以前的心态,这是我目前的Fluent NHibernate设置:
public class Clan
{
public virtual int Clan_Id { get; set; }
[Simple properties]
public virtual IList<Match> Matches { get; set; }
}
public class Match
{
public virtual int Match_Id { get; set; }
[Simple properties]
public virtual Clan Clan { get; set; }
}
以下是映射文件:
public class ClanMap : ClassMap<Clan>
{
public ClanMap()
{
Id(x => x.Clan_Id).Column("Clan_Id").Not.Nullable();
HasMany(x => x.Matches).Table("Matches").KeyColumn("Clan_Id").LazyLoad();
Table("Clans");
}
}
public class MatchMap : ClassMap<Match>
{
public MatchMap()
{
Id(x => x.Match_Id).Column("Match_Id").Not.Nullable();
[simple properties]
References(x => x.Clan).Column("Clan_Id").LazyLoad();
Table("Matches");
}
}
这是我的查询声明:
public static Clan FindClanByName(string name)
{
ISessionFactory mySessionFactory = DatabaseUtilities.GetSessionFactory();
using (ISession mySession = mySessionFactory.OpenSession())
{
using (mySession.BeginTransaction())
{
var find = mySession.QueryOver<Clan>().Where(t => t.Clan_Name == name).List<Clan>();
mySession.Transaction.Commit();
if (find != null && find.Count == 1)
return (Clan)find[0];
else
return null;
}
}
}
当我去访问返回的Clan的匹配列表时,我收到以下错误:
{"Initializing[Counter.Strike.Database.Clan#1]-failed to lazily initialize a collection of role: MyDatabase.Clan.Matches, no session or session was closed"} NHibernate.HibernateException {NHibernate.LazyInitializationException}
我必须尝试过几种不同的映射方法,但没有一种方法可行。有些人给了我这个错误,有些人刚刚返回了一条(第一条)记录(数据库中有6条记录应该返回)。我希望能够访问与Clan相关联的匹配列表,然后是与每个匹配相关联的MatchStats列表(本文中未详细说明,但我确定我可以弄清楚我是否在右侧推送这个决议的方向)。谢谢!
更新1: 我在Clan类中添加了一个构造函数来初始化IList并将我的映射更改为:
HasMany(x => x.Matches).Inverse().Cascade.All();
References(x => x.Clan);
我也改变了我的findclanbyname函数,就像这样:
var find = mySession.QueryOver<Clan>().Where(t => t.Clan_Name == name).List<Clan>();
mySession.Transaction.Commit();
if (find != null && find.Count == 1)
return find[0];
else
return null;
当我逐步执行FindClanByName方法时,我可以在设置断点时看到加载的匹配项,并观察“找到”&#39;变量。一旦该方法返回到调用函数,我将丢失对匹配的引用,并且我得到上述错误。有什么想法吗?
更新2:只是想说nHibernate项目与调用函数位于不同的项目/命名空间中。我正在创建一个围绕nHibernate的包装器。
更新3:我认为这可能是因为我将离开使用声明的可见性。关于如何在会话之外维护引用的任何想法?
答案 0 :(得分:0)
基于错误消息,您似乎在将实体框架知识转换为NHibernate知识时缺少的主要内容是&#34; session&#34;对应于。
EF的DbContext
与NH Session
大致相同。
我没有太多使用EF,但我想如果你在调用DbContext
之前处理了LoadProperty
,你会得到类似的错误,例如:
ObjectContext实例已被释放,不能再用于需要连接的操作。
那么,您是如何在Entity Framework项目中管理DbContext生命周期的呢?你可能应该在这个NHibernate项目中做类似的事情。例如,对于Web应用程序,您通常需要像每个Web请求一样的NHibernate会话。您可以在BeginRequest事件上打开会话,将其存储在HttpContext.Current.Items
集合中,然后在EndRequest事件中处理Session。
你的第二个问题 - 只有在你预期六个时才会找回一条记录 - 这不是return (Clan)find[0]
引起的吗?