我对 NHibernate 很陌生,但我用 google 搜索了一下,没有找到任何可以帮助解决这个问题的东西。我希望你们可以! ;) 我正在更改属性和方法的名称,因为此代码是公司的属性(property),但基本上这就是我需要的帮助。
我有以下情况:
我的域实体:
public class Structure
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Person Manager { get; set; } //I need to fill here.
//and others
}
我的 map 类:
public class MapStructure : ClassMap<Structure>
{
public MapStructure()
{
Table("TB_Structure");
Id(x => x.Id).Column("Id").GeneratedBy.Identity();
Map(x => x.Name).Column("Name");
References<Person>(x => x.Manager).Column("PersonId").Fetch.Join().NotFound.Ignore();
//...
}
}
存储库:
public IEnumerable<T> SelectByColumns()
{
ICriteria searchCriteria = _sessao.CreateCriteria<T>("this");
searchCriteria.CreateAlias("this.Manager", "Manager");
//Only for example purpose. Those columns come as an array string parameter, but the treatment is the same one.
var columns = Projections.ProjectionList();
columns.Add(Projections.Property("Manager.Id"));
columns.Add(Projections.Property("Manager.Name"));
columns.Add(Projections.Property("Manager.Document"));
searchCriteria.SetProjection(columns);
searchCriteria.SetResultTransformer(Transformers.AliasToBean<T>());
return searchCriteria.List<T>();
}
最后是电话:
public IEnumerable<Person> GetManager()
{
using (IDbSession dbSession = _sessionFactory.Create())
{
try
{
IRepository<Structure> _repository = dbSession.CreateRepository<Structure>();
IEnumerable<Structure> structureList = _repository.SelectByColumns();
var managerList = (from structure in structureList
where structure.Manager != null
select new Person()
{
Id = structure.Manager.Id,
Name = structure.Manager.Name,
Document = structure.Manager.Document
});
return managerList.OrderBy(x => x.Name);
}
catch (Exception)
{
throw;
}
}
}
这会生成一个如下所示的 sql 查询:
SELECT manager1_.PersonId as y0_, manager1_.Name as y1_, manager1_.Document as y2_
FROM TB_Structure this_
inner join TB_Person manager1_ on this_.ManagerId=manager1_.PersonId
这正是我所需要的。如果我在管理工作室中运行此查询,我会得到我期望的所有结果。
但是当我到达 var managerList 时,structuralList 包含从 sql 返回的所有记录,但全部都带有 null 值,如下所示:
我已经尝试过 CreateAlias、CreateCriteria、返回 IList<>、返回 IEnumerable。 我已经将 Transformers.AliasToBean() 更改为 Transformers.AliasToEntityMap。 我在谷歌上搜索了很多不同的东西,但总是得到相同的结果。
感谢您的帮助,并感谢您抽出时间!
最佳答案
你就快到了。我们需要的是将投影正确转换为实体/对象树。这需要两个步骤:
我。为每列使用别名
列别名对于事后处理比 SQL 语句生成更有用。但这是下一步必须做的。所以代替这个:
columns.Add(Projections.Property("Manager.Id"));
columns.Add(Projections.Property("Manager.Name"));
columns.Add(Projections.Property("Manager.Document"));
我们需要这个:
columns.Add(Projections.Property("Manager.Id").As("Manager.Id");
columns.Add(Projections.Property("Manager.Name").As("Manager.Name"));
columns.Add(Projections.Property("Manager.Document").As("Manager.Document"));
事实上,如果我们使用第一级(无 JOIN)实体,这就足够了。对于 JOINed 引用树(多对一),它不起作用。但是
二.使用自定义结果转换器
一如既往,NHibernate 为自定义扩展提供了许多开放点。其中之一是自定义 IResultTransformer。准备好处理我们需要的引用树就在这里:
在我们的解决方案中,我们应该代替这个:
searchCriteria.SetResultTransformer(Transformers.AliasToBean<T>());
使用这个:
searchCriteria.SetResultTransformer(new DeepTransformer<T>());
此实现强烈依赖于正确的别名设置,描述真实的实体属性(使用反射来查找要设置的内容)。所以第一点——列/属性别名非常重要
关于c# - Fluent NHibernate - ProjectionList - ICriteria 返回空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26066085/