假设我有一个名为 Pet 的基类和两个继承 Pet 的子类 Cat 和 Dog。
我只是将它们映射到三个表 Pet、Cat 和 Dog,其中 Pet 表包含基类属性,Cat 和 Dog 表包含 Pet 表的外键以及特定于猫或狗的任何附加属性。联合子类策略。
现在,使用 NHibernate 和 ICriteria,我怎样才能获得所有不同宠物的列表作为 Pet 对象,而不是 Cat 或 Dog 对象 - 只是普通的 Pet 对象,而不与其他表进行任何连接?我只对宠物中包含的信息感兴趣。
假设我有一个名为 Pet 的基类和两个继承 Pet 的子类 Cat 和 Dog。
我只是将它们映射到三个表 Pet、Cat 和 Dog,其中 Pet 表包含基类属性,Cat 和 Dog 表包含 Pet 表的外键以及特定于猫或狗的任何附加属性。联合子类策略。
现在,使用 NHibernate 和 ICriteria,我怎样才能获得所有不同宠物的列表作为 Pet 对象,而不是 Cat 或 Dog 对象 - 只是普通的 Pet 对象,而不与其他表进行任何连接?我只对宠物中包含的信息感兴趣。
我刚刚做了类似的事情,发现Ayende的这篇博文非常有帮助!我采用了加入子类的方法,它很好地支持查询基类。
但是,要在不加入的情况下找到“唯一的宠物”,我认为您需要每类表的层次结构方法。或者,您可以使用每个子类的表,只对子类进行左连接,并将其限制为在任何左连接上都没有匹配的行。
对于许多情况来说已经足够好了:将属性投影到对象本身中。
小心使用,因为对象已损坏,因为它没有正确的类型
var propsToSelect = Projections.ProjectionList();
foreach (var prop in sessionfactory.GetClassMetadata(typeof(Pet)).PropertyNames)
{
propsToSelect.Add(Projections.Property(prop.Name), prop.Name);
}
var results = session.CreateCriteria<Pet>()
.SetProjection(propsToSelect)
.SetResultTransformer(Transformers.AliasToBean<Pet>())
.List<Pet>();
嗯,我认为选择“作为宠物”会带回所有对象(不仅仅是未分类的宠物)。我不知道这样做的干净方式,但我不是NH专家。
也许您可以直接查询父表中的鉴别器列? 尽管您可能不得不使用自定义 SQL 查询而不是 HQL 或 ICriteria。
我不相信你可以用 Criteria API 做到这一点。但是,您可以使用 HQL 做到这一点:
var hql = @"from Pet p where p.class = Pet";
为什么不为“PetsOnly”创建一个新地图并删除您的鉴别器和其他非必填字段?我认为上面的克里斯托弗暗示了同样的事情。仍应为您提供完整的插入更新和删除选择支持。宠物只是Pet
...
这似乎工作正常:
我创建了一个视图,选择了Pet表上的所有列。然后,我创建了一个映射到视图的简单 DTO 类。之后,可以使用 ICriteria。
也许不是最漂亮或最干净的解决方案,但肯定比动态查询字符串更容易使用。