我正在尝试连接2个表,并直接投影到DTO(NHibernate 5)。 我有以下实体:
public class Person {
public Guid Id {get;set;}
public string Name {get;set;}
}
public class Car {
public Guid Id {get;set;}
public string Brand {get;set;}
public Person Owner {get;set;}
}
如我们所见,Car到Person只是一个参考(car知道它的所有者),这在我的整个项目中都是可以的。
但是,在一个地方,我需要查询所有“人员”,并使每个人都拥有自己拥有的汽车。
我创建了这样的DTO:
public class PersonDto {
public Guid Id {get;set;}
public string Name {get;set;}
public IList<CarDto> {get;set;}
}
public class CarDto {
public Guid Id {get;set;}
public string Brand {get;set;}
}
是一种呈现颠倒链接在一起的数据的形式。 使用SQL或LINQ(GroupJoin)执行此任务似乎微不足道,但由于在NH中未实现GroupJoin,因此我发现它在NH中极其困难。
能帮我解决上述问题吗?
答案 0 :(得分:0)
只需将Car
集合添加到现有的Person
实体和mark the collection inverse。 NHibernate中的集合默认情况下是惰性的,因此,当您查询Person
时,它将不会从数据库读取汽车,直到您开始对其进行迭代。换句话说,添加Car
集合不会影响代码的工作方式。
当您想有效地查询汽车的相关人员时,请强制NH进行加入
.QueryOver<Person>.Fetch(person => person.Cars).Eager
答案 1 :(得分:0)
我想回答我自己的问题。感谢Rafal Rutkowski的投入。
要获取仅在1个方向上具有关联的数据,我们需要引入一个新的数据模型,然后将结果手动转换为我们的实体。我希望以下示例是最好的答案:
1)创建此类数据模型以存储NH响应:
private class PersonCarModelDto
{
public Guid PersonId { get; set; }
public string PersonName { get; set; }
public Guid CarId { get; set; }
public string CarBrand { get; set; }
}
2)创建一个这样的模型来存储分层数据作为输出:
private class PersonModel
{
public Guid Id { get; set; }
public string Name { get; set; }
public IList<CarModel> Cars { get; set; }
}
private class CarModel
{
public Guid Id { get; set; }
public string Brand { get; set; }
}
3)现在是NH查询:
Person personAlias = null;
Car carAlias = null;
PersonCarModelDto resultAlias = null;
var response = GetCurrentSession().QueryOver<Car>(() => carAlias) // notice we are going from from 'downside' entity to 'up'
.Right.JoinAlias(c => c.Owner, () => personAlias) // notice Right join here, to have also Persons without any car
.SelectList(list => list
.Select(() => personAlias.Id).WithAlias(() => resultAlias.PersonId)
.Select(() => personAlias.Name).WithAlias(() => resultAlias.PersonName)
.Select(() => carAlias.Id).WithAlias(() => resultAlias.CarId)
.Select(() => carAlias.Brand).WithAlias(() => resultAlias.CarBrand)
.TransformUsing(Transformers.AliasToBean<PersonCarModelDto>())
.List<PersonCarModelDto>()
;
4)现在我们将平面数据作为PersonCarModelDto的列表,但我们要创建输出模型:
var modelResult = response.GroupBy(p => p.PersonId)
.Select(x => new PersonModel
{
Id = x.Key,
Name = x.Select(y => y.PersonName).First(), // First() because each PersonName in that group is the same
Cars = x.Select(y => new CarModel
{
Id = y.CarId,
Name = y.CarBrand
})
.ToList()
})
.ToList()
;
结论: