NHibernate查询指定嵌套属性映射失败求助
解决NHibernate QueryOver嵌套属性映射到实体的问题
嘿,我懂你碰到的麻烦了——你用Transformers.AliasToBean的时候,直接映射company_product.Company.Name这种嵌套属性会失败,这是因为默认的AliasToBean转换器不支持嵌套对象的属性赋值,它只能处理实体类的顶级属性,没法自动帮你实例化嵌套的Company或Product对象并设置它们的属性。
下面给你几个实用的解决方案:
方案1:使用AliasToBeanNestedResultTransformer(推荐)
NHibernate有一个扩展的结果转换器AliasToBeanNestedResultTransformer,专门用来处理嵌套属性的映射。你只需要替换原来的转换器即可:
Company_Product company_product = null; Company company = null; Product product = null; IList<Company_Product> test = session.QueryOver<Company_Product>() .Left.JoinAlias(cp => cp.Company, () => company) .Left.JoinAlias(cp => cp.Product, () => product) .SelectList(list => list .Select(cp => cp.Company.Id).WithAlias(() => company_product.Company.Id) .Select(cp => cp.Company.Name).WithAlias(() => company_product.Company.Name) .Select(cp => cp.Product.Id).WithAlias(() => company_product.Product.Id) .Select(cp => cp.Product.Name).WithAlias(() => company_product.Product.Name) .Select(cp => cp.SalesDate).WithAlias(() => company_product.SalesDate) ) // 替换成支持嵌套的结果转换器 .TransformUsing(Transformers.AliasToBeanNested<Company_Product>()) .List<Company_Product>();
注意:如果你的NHibernate版本较旧,可能需要确认项目已引用包含该转换器的扩展包,部分版本需要手动引入相关程序集。
方案2:手动构造实体对象
如果不想依赖扩展转换器,你可以直接在查询中获取所有需要的字段,手动创建并组装实体对象:
Company company = null; Product product = null; var test = session.QueryOver<Company_Product>() .Left.JoinAlias(cp => cp.Company, () => company) .Left.JoinAlias(cp => cp.Product, () => product) .SelectList(list => list .Select(cp => cp.Id) .Select(cp => cp.SalesDate) .Select(company => company.Id) .Select(company => company.Name) .Select(product => product.Id) .Select(product => product.Name) ) .List<object[]>() .Select(arr => new Company_Product { Id = (int)arr[0], SalesDate = (DateTime)arr[1], Company = new Company { Id = (int)arr[2], Name = (string)arr[3] }, Product = new Product { Id = (int)arr[4], Name = (string)arr[5] } }) .ToList();
这种方式代码量稍大,但完全不需要额外依赖,逻辑清晰也好调试。
方案3:使用DTO中转
你可以先定义一个扁平化的DTO类,把所有需要的字段放在顶级,用AliasToBean映射到DTO后,再转换成实体类:
首先定义DTO:
public class CompanyProductDto { public int Id { get; set; } public DateTime SalesDate { get; set; } public int CompanyId { get; set; } public string CompanyName { get; set; } public int ProductId { get; set; } public string ProductName { get; set; } }
然后执行查询并转换:
CompanyProductDto dto = null; Company company = null; Product product = null; var dtoList = session.QueryOver<Company_Product>() .Left.JoinAlias(cp => cp.Company, () => company) .Left.JoinAlias(cp => cp.Product, () => product) .SelectList(list => list .Select(cp => cp.Id).WithAlias(() => dto.Id) .Select(cp => cp.SalesDate).WithAlias(() => dto.SalesDate) .Select(company => company.Id).WithAlias(() => dto.CompanyId) .Select(company => company.Name).WithAlias(() => dto.CompanyName) .Select(product => product.Id).WithAlias(() => dto.ProductId) .Select(product => product.Name).WithAlias(() => dto.ProductName) ) .TransformUsing(Transformers.AliasToBean<CompanyProductDto>()) .List<CompanyProductDto>(); // 转换成目标实体类 var test = dtoList.Select(dto => new Company_Product { Id = dto.Id, SalesDate = dto.SalesDate, Company = new Company { Id = dto.CompanyId, Name = dto.CompanyName }, Product = new Product { Id = dto.ProductId, Name = dto.ProductName } }).ToList();
这三种方案里,方案1最简洁,方案2最灵活,方案3适合复杂场景下的解耦,你可以根据自己的项目情况选择~
内容的提问来源于stack exchange,提问作者RYan.A
相关产品推荐
相关产品推荐

