【发布时间】:2011-07-29 19:14:17
【问题描述】:
我在 SQL Azure 中使用实体框架,在我的应用程序的一个页面中,我们向用户展示了相当多的相关数据。我们在页面上最多加载 30 个项目,但每个项目都有 5 个与其他对象的一对多映射。查询时间处于合理水平,但我在对象映射上泄露了相当多的性能。 (几乎整整一秒)。
这是我的对象的外观示例
public class Task
{
public string Name {get; set;}
public string Status {get; set;}
public DateTime DueDate {get; set;}
public IEnumerable<TaskData> Data {get; set;}
public IEnumerable<Transaction> Transactions {get; set;}
public IEnumerable<File> Files {get; set;}
public IEnumerable<Comment> Comments {get; set;}
public IEnumerable<People> People {get; set;}
}
任务有名称、状态和截止日期。它还具有 许多 自定义名称/值对的 TaskData、许多 显示任务历史记录的事务、许多 文件、许多评论和许多工作的人。
我的 EF 查询看起来像这样。
var Items = context.Items.Include(x=>x.Data).Include(x=>x.Files).Include(x=>x.Comments).Include(x=>x.People).Where(some constraint).ToList();
特定任务的相关性首先取决于状态,然后取决于截止日期。所以我创建了一个 IComparable 覆盖以用于排序。关键是分页查询在这种情况下效果不佳,因为排序不是基于 int 或日期(对吗?)
在我们的应用程序的其余部分中,我们显示的关于每个任务的信息较少,而 Linq2Entities 工作得很好。在这种情况下,对象映射正在杀死我们。我已经走上了使用 Dapper 直接进入数据库的道路,但一对多映射有它的警告。对于一些关系,我认为它会运作良好,但不适用于 5-6。我接下来要看的是 PetaPoco,但没走多远,我就想我最好先把这个问题放在这里。
我想带回这么多数据是不是疯了?我有哪些选择可以从中获得最大性能?因为它只是应用程序的一个领域,所以我会稍微复杂一点。
【问题讨论】:
-
“我想带回这么多数据是不是疯了?”好吧,你正在做相当于
SELECT *。这真的是你需要的吗?还是您只需要每个字段中的几个字段?如果是这样,投影到视图模型上会快得多。 -
不,你说得对,我只需要几个字段。你是说我应该做 .Select(new TaskViewModel{...}); 而不是 .ToList()在这种情况下,EF 会编译更高效的查询吗?
-
Yes, by far.。这不是唯一更快的事情。试试看!
-
是的,我会试一试。也许我把问题复杂化了。我使用 ViewModel 但不直接投影到它。感谢您的帮助。
-
@Naor:他可以,但是延迟加载的 N+1 性能可能是最慢的选项。延迟加载是 ORM 在性能方面名声不佳的原因。
标签: sql-server entity-framework dapper petapoco