Orm rk代表。它有一个品牌对象,在网站主页上,商店出售的所有品牌都列在左侧。要显示此品牌菜单,网站只需整数BrandId和字符串BrandName。但是品牌对象包含大量其他属性,最显著的是描述属性,该属性可以包含大量关于品牌的文本。没有两种方法,加载所有关于品牌的额外信息只是为了在无序列表中吐出品牌名称,(1)速度明显缓慢,通常是因为文本字段太大;(2)在内存使用方面效率非常低,积累了大量字符串,甚至在扔掉它们之前都不看它们

Orm rk代表。它有一个品牌对象,在网站主页上,商店出售的所有品牌都列在左侧。要显示此品牌菜单,网站只需整数BrandId和字符串BrandName。但是品牌对象包含大量其他属性,最显著的是描述属性,该属性可以包含大量关于品牌的文本。没有两种方法,加载所有关于品牌的额外信息只是为了在无序列表中吐出品牌名称,(1)速度明显缓慢,通常是因为文本字段太大;(2)在内存使用方面效率非常低,积累了大量字符串,甚至在扔掉它们之前都不看它们,orm,Orm,许多ORM提供的一个选项是延迟加载属性。因此,我们可以将一个Brand对象返回给我们,但这个耗时且浪费内存的Description字段直到我们尝试调用它的get访问器。此时,代理对象将截获我们的调用,并及时从数据库中提取描述。这有时已经足够好了,但已经让我受够了,我个人不推荐: 很容易忘记该属性是延迟加载的,仅通过编写foreach循环就引入了selectn+1问题。谁知道林克介入后会发生什么 如果由于传输混乱或网络中断而导致实时数据库调用失败怎么办?我几乎可以保证,任何正在做像string

许多ORM提供的一个选项是延迟加载属性。因此,我们可以将一个
Brand
对象返回给我们,但这个耗时且浪费内存的
Description
字段直到我们尝试调用它的
get
访问器。此时,代理对象将截获我们的调用,并及时从数据库中提取描述。这有时已经足够好了,但已经让我受够了,我个人不推荐:

  • 很容易忘记该属性是延迟加载的,仅通过编写foreach循环就引入了selectn+1问题。谁知道林克介入后会发生什么
  • 如果由于传输混乱或网络中断而导致实时数据库调用失败怎么办?我几乎可以保证,任何正在做像
    string desc=brand.Description
    这样无害的事情的代码都不会期望简单的调用抛出
    DataAccessException
    。现在你已经以一种令人不快和意想不到的方式崩溃了。(是的,我看到我的应用程序因为这个原因很难运行。我学到了很多!)
因此,我最终要做的是,在需要性能或容易出现数据库死锁的场景中,我创建了一个单独的界面,网站或任何其他程序都可以调用该界面来访问经过仔细检查的特定数据块。架构最终看起来有点像这样(请原谅ASCII艺术):

网站:控制器类 | |---------------------------------+ | | 应用程序服务器:IDocumentService、IInventoryService等 (数组、数据集)(常规OO对象,如品牌) | | | | | | 数据层:(原始ADO.NET返回数组,(“全脂”ORM,如NHibernate) 数据集(简单类) 我曾经认为这是欺骗,颠覆了OO对象模型。但从实际意义上讲,只要你用这个快捷方式来显示数据,我认为没关系。更新/插入以及您仍然在经历完全水合的、ORM填充的域模型,这种情况发生的频率(在我的大多数情况下)远远低于显示特定的数据子集。像NHibernate这样的ORM可以让你做投影,但到那时我看不到ORM的意义。无论如何,这可能是一个存储过程,编写ADO.NET需要两秒钟


这只是我的两分钱。我期待着阅读其他一些回复。

人们使用ORM是为了提高开发效率,而不是为了优化运行时性能。这取决于项目是否更重要的是最大化开发效率还是运行效率

在实践中,可以使用ORM来获得最高的生产率,然后在完成后对应用程序进行概要分析以确定瓶颈。只有在您获得最大回报的情况下,才使用自定义SQL查询替换ORM代码

如果您通常需要表中的所有列,那么选择*也不错。我们不能概括通配符总是好的还是坏的

编辑:Re:doofledorfer的评论。。。就我个人而言,我总是显式地命名查询中的列;我从不在生产代码中使用通配符(尽管我在执行特殊查询时使用通配符)。最初的问题是关于ORM的——事实上,ORM框架统一发布一个
SELECT*
来填充相应对象模型中的所有字段并不少见

执行
SELECT*
查询可能并不一定表明您需要所有这些列,也不一定意味着您忽略了代码。可能是ORM框架正在生成SQL查询,以确保所有字段在您需要时都可用。

或的任何实现使用一种语法,最终使您能够控制所选数据。查询的定义也是其结果集的定义

这通过从ORM中删除数据形状职责,巧妙地避免了
select*
问题

例如,要选择所有列,请执行以下操作:

from c in data.Customers
select c
要选择子集,请执行以下操作:

from c in data.Customers
select new
{
  c.FirstName,
  c.LastName,
  c.Email
}
要选择组合,请执行以下操作:

from c in data.Customers
join o in data.Orders on c.CustomerId equals o.CustomerId
select new
{
  Name = c.FirstName + " " + c.LastName,
  Email = c.Email,
  Date = o.DateSubmitted
}

选择*强烈表明您对应用程序及其模块的范围没有设计控制权。清理别人的工作的一个主要困难是,里面有些东西是没有目的的,但没有说明什么是需要和使用的,什么不是

应用程序中的每一段数据和代码都应该有特定的用途,并且应该指定用途,或者易于检测

我们都知道,也都鄙视那些不太担心事情为什么会起作用的程序员,他们只是喜欢尝试一些东西,直到预期的事情发生,然后在下一次结束
from c in data.Customers
join o in data.Orders on c.CustomerId equals o.CustomerId
select new
{
  Name = c.FirstName + " " + c.LastName,
  Email = c.Email,
  Date = o.DateSubmitted
}