有人能更好地解释一下nHibernate中的“投影”是什么吗?

30
作为 nHibernate 及其实用库 Fluent NHibernate 的新用户,我正在努力学习足够的知识,以便在使用良好的数据库时能够做到危险水平。
我非常难以理解“投影”的概念。具体来说,“它们到底是什么?”
我已经进行了准确搜索“什么是投影?”,“nHibernate 中的项目”和“nHibernate、投影、定义”等等。但我仍然感到非常困惑。到目前为止,最有帮助的帖子是这个 StackOverflow 问题Colin Ramsay 的这篇博客文章。但我仍然非常困惑。我的数据库知识最多只能算入门级别。

我并不真正理解什么是投影,为什么我想要使用它们,它们所完成的任务等等。我在博客文章中看到他正在使用它们来获取整数列表(我假设是主键),以便他可以在不同的查询中使用它们,但这种功能和原因有点模糊。

3个回答

77
这是一个实际的例子。假设你有一个在线商店,其中一个域类别是“Brand”,如“三星”。这个类别有许多与之相关的属性,可能是一个整数“Identity”,一个“Name”,一个自由文本“Description”字段,一个对“Vendor”对象的引用等等。
现在假设你想显示一个菜单,列出在线商店提供的所有品牌。如果你只是做session.CreateCriteria<Brand>().List(),那么你确实会得到所有品牌。但你也会从数据库中吸取所有长的“Description”字段和对“Vendor”的引用,你并不需要这些来显示菜单;你只需要“Name”和“Identity”。就性能而言,从数据库中抽取所有这些额外的数据会拖慢速度并且是不必要的。
相反,你可以创建一个“projection”对象,它只包含“Identity”和“Name”,称之为“NameIdentityPair”。
public class NameIdentityPair
{
    public int Identity { get; set; }
    public string Name { get; set; }
}

你可以通过告诉NHibernate将结果集转换为你的投影,从而仅选择执行任务所需的数据:

var brandProjections = this.session.CreateCriteria<Brand>()
    .SetProjection(Projections.ProjectionList()
        .Add(Projections.Property("Name"), "Name")
        .Add(Projections.Property("Identity"), "Identity"))
    .SetResultTransformer(Transformers.AliasToBean<NameIdentityPair>())
    .List<NameIdentityPair>();

foreach (var brandProjection in brandProjections)
{
    Console.WriteLine(
        "Identity: {0}, Name: {1}", 
        brandProjection.Identity, 
        brandProjection.Name);
}

现在你有的不是一个Brand列表,而是一个NameIdentityPair列表,NHibernate只会发出一个类似于SELECT b.Identity, b.Name from dbo.Brand b的SQL语句来获得这个投影,而不是一条巨大的SQL语句来获取一个Brand对象所需的所有内容(例如,SELECT b.Identity, b.Name, b.Description from dbo.brand b left join dbo.vendor v ....)。

希望这可以帮助到你。


2
投影(Projection)就像查询端的限制器,而不是查询结果的限制器。在正常情况下,我会创建 NameIdentityPair 对象,并将查询结果映射到它上面,但是使用投影,我可以直接在查询中指定精确的过滤条件,这就是数据库所知道的全部。 - Derek
5
许多应用程序更频繁地读取而不是写入数据,因此一种常见的模式是在从数据库读取时使用投影(projections),并在保存到数据库时使用完全加载的领域对象(fully hydrated domain objects)。这样,从数据库读取的性能得到优化,而向数据库写入数据则利用了业务逻辑(编写在您的领域类中)和所使用的工具(NHibernate 可以帮助您节省大部分 CRUD 代码)。"投影"有点像挑选出您将需要的数据,这样当 NHibernate 进行 SQL 查询时,它只会向数据库请求这些数据。 - Nicholas Piasecki
谢谢,我认为这比我之前找到的要清晰得多。 - Derek

2
如果您熟悉SQL,那么投影就是查询的SELECT子句,用于选择要返回的可用结果中的哪些字段。
例如,假设你有一个Person,拥有FirstName、LastName、Address和Phone字段。如果您希望查询返回所有内容,则可以省略投影,这类似于SQL中的SELECT * FROM Person。如果您只想要名字和姓氏,您可以创建一个包含FirstName和LastName的投影——在SQL术语中,这将是SELECT FirstName,LastName FROM Person。

1
您可以使用投影来调用 SQL 函数,例如 SUM、COUNT... 或者选择单个字段而不返回实体。
“...仅检索实体或实体的属性,而无需在事务范围内加载实体本身的开销。有时称为报告查询;更正确地称为投影。” [《NHibernate 实战》]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接