[英]Why does Automapper and NHibernate result in N+1?
I created this query with NHibernate: 我使用NHibernate创建了此查询:
public IList<Category> GetCategoriesByUsername(string username)
{
Category cAlias = null;
User uAlias = null;
Keyword kAlias = null;
var categories = SessionFactory.GetCurrentSession().QueryOver<Category>(() => cAlias)
.JoinAlias(() => cAlias.User, () => uAlias)
.Where(() => uAlias.Username == username)
.Future<Category>();
var keywords = SessionFactory.GetCurrentSession().QueryOver<Keyword>(() => kAlias)
.JoinAlias(c => c.Category, () => cAlias)
.Where(() => cAlias.Id == kAlias.Category.Id)
.Future<Keyword>();
IList<Category> list = (List<Category>)categories.ToList();
return list;
}
This works fine and gives me a list of categories where each category has its own keywords. 这可以正常工作,并为我提供了一个类别列表,其中每个类别都有其自己的关键字。 In my service layer I try to convert it to a ViewModel with Automapper which works but not as expected. 在我的服务层中,我尝试使用Automapper将其转换为ViewModel,但是可以正常使用。 For every keyword in the category list it creates a new query (N+1). 对于类别列表中的每个关键字,它都会创建一个新查询(N + 1)。 It doesn't use the already populated keywords in each category in the list. 它不使用列表中每个类别中已经填充的关键字。
These are my Models and ViewModels: 这些是我的模型和ViewModels:
public class Category
{
public virtual Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Keyword> Keywords { get; set; }
public virtual User User { get; set; }
}
public class CategoryView
{
public int Id { get; set; }
public string Name { get; set; }
public IList<KeywordSummaryView> Keywords { get; set; }
}
public class Keyword
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual Category Category { get; set; }
}
public class KeywordSummaryView
{
public int Id { get; set; }
public string Name { get; set; }
}
My mapping: 我的映射:
public class AutoMapperBootStrapper
{
public static void ConfigureAutoMapper()
{
Mapper.CreateMap<Category, CategoryView>();
Mapper.CreateMap<Keyword, KeywordSummaryView>();
}
}
public static class CategoryMap
{
public static IList<CategoryView> ConvertToCategoryView(this IList<Category> category)
{
return Mapper.Map<IList<Category>, IList<CategoryView>>(category);
}
}
From Model to ViewModel: 从模型到视图模型:
IList<Category> categories = _categoryRepository.GetCategoriesByUsername(request.Username);
response.Categories = categories.ConvertToCategoryView();
It doesn't use the already populated keywords in each category in the list but instead creates a new query for each keyword (N+1). 它不使用列表中每个类别中已经填充的关键字,而是为每个关键字(N + 1)创建一个新查询。 Is there something I'm doing wrong? 我做错了什么吗?
I guess both of these should prevent N+1 select 我猜这两个都应该阻止N + 1选择
public IList<Category> GetCategoriesByUsername(string username)
{
User uAlias = null;
var categories = SessionFactory.GetCurrentSession().QueryOver<Category>(() => cAlias)
.Fetch(x => x.Keywords ).Eager
.JoinAlias(() => cAlias.User, () => uAlias)
.Where(() => uAlias.Username == username);
.TransformUsing(Transformers.DistinctRootEntity)
.List<Category>();
return categories ;
}
public IList<Category> GetCategoriesByUsername(string username)
{
User uAlias = null;
Keyword kAlias = null;
var categories = SessionFactory.GetCurrentSession().QueryOver<Category>(() => cAlias)
.JoinAlias(() => cAlias.User, () => uAlias)
.JoinAlias(x => x.Keywords , () => kAlias, JoinType.LeftOuterJoin)
.Where(() => uAlias.Username == username);
.TransformUsing(Transformers.DistinctRootEntity)
.List<Category>();
return categories;
}
Hope this will help 希望这会有所帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.