当经过Automapper时,NHibernate加载的树会命中数据库
我遇到了一个奇怪的NHibernate和Automapper问题。我不确定是谁的错,但我现在挣扎了一整天,我似乎不知道为什么 以下是我的Nhibernate映射文件: Navigation.hbm.xml当经过Automapper时,NHibernate加载的树会命中数据库,nhibernate,lazy-loading,automapper,hierarchy,eager-loading,Nhibernate,Lazy Loading,Automapper,Hierarchy,Eager Loading,我遇到了一个奇怪的NHibernate和Automapper问题。我不确定是谁的错,但我现在挣扎了一整天,我似乎不知道为什么 以下是我的Nhibernate映射文件: Navigation.hbm.xml <id name="ID" column="NavigationID"> <generator class="identity"></generator> </id> <property name="IsDefault"/> &
<id name="ID" column="NavigationID">
<generator class="identity"></generator>
</id>
<property name="IsDefault"/>
<property name="RoleType" column="RoleTypeID" />
<bag name="Items" cascade="save-update" inverse="true" lazy="false" fetch="join">
<key column="NavigationID"/>
<one-to-many class="NavigationItem"/>
</bag>
然后,当Automapper发挥作用时,将生成这些查询的列表,只有p0参数不同(从1到12…没有父项的项数)
这是从NHProf应用程序中获取的,希望对您有所帮助
谢谢,,
Cosmin我认为AutoMapper正在递归地映射您的类。如果是这种情况,则可以使用指定映射的最大深度
Mapper.CreateMap<TSource, TDestination>().MaxDepth(2); // or 1, or 3, or whatever
Mapper.CreateMap().MaxDepth(2);//或者1,或者3,或者别的什么
Hi Cosmin,你能发布执行的SQL吗?你好,James,我已经用生成的SQL编辑了这个问题。是的,有,但我想要这个。问题是,我希望AutoMapper递归地映射它们,但不命中数据库。信息都在那里,由NHIbernate加载。我的问题是,为什么当AutoMapper遍历对象层次结构时,NHibernate认为他需要点击数据库?因此调用navigation.Items[0]。Items[0]不会触发数据库查询?不确定,但我不认为每个NavigationItem.Items集合都是从您的查询映射的。也许在包上指定批量大小可以通过批处理请求来提高性能。我目前正在处理一个NHibernate项目,该项目在我的实体中有很多层次关系,我发现如果不使用单独的多对多联接表,就很难用一个查询加载所有集合的整个聚合根,就像在这篇博文中所说的,这都是关于NHibernate延迟加载的。Automapper尝试映射所有属性(引用),以便通过反射命中对象上具有代理的一些属性。之后,nHibernate认为您需要该对象或集合,它会延迟加载数据。是的,但问题是他的模型是分层的,因此AutoMapper会递归加载未加载的整个图形属性。即使他正在查询所有实体,但这并不意味着它们之间的所有关系都已设置。
ISession session = SessionProvider.Instance.CurrentSession;
using (transaction = session.BeginTransaction())
{
var navigation = session.QueryOver<Navigation>()
.Where(x => x.IsDefault && x.RoleType == null)
.TransformUsing(new NHibernate.Transform.RootEntityResultTransformer())
.SingleOrDefault();
transaction.Commit();
return navigation;
}
public class NavigationModel
{
public List<NavigationItemModel> Items { get; set; }
public NavigationModel()
{
Items = new List<NavigationItemModel>();
}
}
public class NavigationItemModel
{
public string PageName { get; set; }
public string Url { get; set; }
public bool Selected { get; set; }
public NavigationItemModel Parent { get; set; }
public List<NavigationItemModel> Items { get; set; }
}
AutoMapper.Mapper
.CreateMap<NavigationItem, NavigationItemModel>()
// IF I REMOVE THE NEXT LINE, IT HITS THE DATABASE FOR EACH SUB-ITEM of the NavigationItem.Items
.ForMember(m => m.Items, o => o.Ignore());
AutoMapper.Mapper
.CreateMap<Navigation, NavigationModel>();
SELECT this_.NavigationID as Navigati1_7_2_,
this_.IsDefault as IsDefault7_2_,
this_.RoleTypeID as RoleTypeID7_2_,
items2_.NavigationID as Navigati5_4_,
items2_.NavigationItemID as Navigati1_4_,
items2_.NavigationItemID as Navigati1_4_0_,
items2_.ShowInMenu as ShowInMenu4_0_,
items2_.[Order] as column3_4_0_,
items2_.PageID as PageID4_0_,
items2_.NavigationID as Navigati5_4_0_,
items2_.ParentNavigationItemID as ParentNa6_4_0_,
page3_.PageID as PageID8_1_,
page3_.Name as Name8_1_,
page3_.Title as Title8_1_,
page3_.Description as Descript4_8_1_,
page3_.URL as URL8_1_
FROM Navigation this_
left outer join NavigationItem items2_
on this_.NavigationID = items2_.NavigationID
left outer join Page page3_
on items2_.PageID = page3_.PageID
WHERE (this_.IsDefault = 1 /* @p0 */
and this_.RoleTypeID is null)
SELECT items0_.ParentNavigationItemID as ParentNa6_2_,
items0_.NavigationItemID as Navigati1_2_,
items0_.NavigationItemID as Navigati1_4_1_,
items0_.ShowInMenu as ShowInMenu4_1_,
items0_.[Order] as column3_4_1_,
items0_.PageID as PageID4_1_,
items0_.NavigationID as Navigati5_4_1_,
items0_.ParentNavigationItemID as ParentNa6_4_1_,
page1_.PageID as PageID8_0_,
page1_.Name as Name8_0_,
page1_.Title as Title8_0_,
page1_.Description as Descript4_8_0_,
page1_.URL as URL8_0_
FROM NavigationItem items0_
left outer join Page page1_
on items0_.PageID = page1_.PageID
WHERE items0_.ParentNavigationItemID = 1 /* @p0 */
Mapper.CreateMap<TSource, TDestination>().MaxDepth(2); // or 1, or 3, or whatever