从LINQ升级到SQL时,如何最小化性能损失?

dev*_*xer 3 c# entity-framework code-first sql-server-ce linq-to-sql

我最近更新了一个使用LINQ to SQL和SQL Server CE 3.5到Entity Framework 4.1 Code First和SQL Server CE 4.0的应用程序,它现在运行速度明显变慢.在秒表测试之前和之后我做了一些,我的应用程序的大多数主要操作平均运行速度慢了约40%.

我正在使用EF Code First的所有默认策略和配置,但禁用级联删除除外.

当我最初发布这个问题时,我专注于一个似乎花了很长时间的查询,但我已经意识到它在第一次运行时只是特别慢(参见下面的评论帖子).

我现在认为我看到的是大多数查询运行速度较慢 - 速度不是很慢,但速度足够快,因为应用程序执行的大多数操作都涉及多个查询.

这个应用程序有一个非常小的数据库 SQL CE(.sdf)文件只有458 KB,最大的表少于250条记录.

这是一个POCO类示例:

public class Target
{
    public int Id { get; set; }
    public int TrialDefinitionId { get; set; }
    public int Number { get; set; }
    public int X { get; set; }
    public int Y { get; set; }
    public string Phase { get; set; }
    public virtual TrialDefinition TrialDefinition { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的所有类都遵循这个基本模式(简单类型+虚拟属性来获取通过外键链接的对象).我有一个类ICollection用于获取多对一关系的列表.

最后说明:我使用存储库模式作为中介,并且存储库的每个用法都放在一个using块中.对于"get"操作,一旦我从数据库中获取了所需的数据,就会导致实体分离.

有没有人有任何具体的策略来改善我的EF Code First应用程序的性能?请记住,我还没有机会详细阅读EF.我主要是尝试尽可能快速,轻松地从LINQ to SQL迁移到EF.对我来说最有用的答案是包含更改特定策略或配置或其他设置的答案.

Aka*_*ava 5

最后说明:我使用存储库模式作为中介,并且存储库的每个用法都放在一个使用块中.对于"get"操作,一旦我从数据库中获取了所需的数据,就会导致实体分离.

那不是必需的......

  1. 实体框架的默认架构已经实现了存储库模式.
  2. 保持ObjectContext存活并不意味着您保持与数据库的连接.
  3. 仅当您从数据库加载或保存更改时,才会获取连接池中的新连接并执行操作.

当然,使用块会减慢因为每个使用块会做以下,

  1. 初始化上下文(需要从资源加载元数据)
  2. 验证一些事情
  3. 打开与DB的连接
  4. 执行你的任务
  5. 清理并关闭数据库

现在,前两个步骤肯定会采取大量的时间,你将有相同类型的应用寿命更长的多个对象,因为每一个新的上下文将每个查询创建同一个对象的新副本.

实体框架已经实现了标识映射,这意味着它会不断的对象活着,对象在整个上下文的生命期,这将不仅节省内存,但也将更快地执行相同的主键只有一个副本.

我建议不要在每个查询或更小的步骤中使用块,而应该在应用程序的整个生命周期中保持ObjectContext的活动状态.而且您根本不需要实现缓存或存储库.

  • 假设在应用程序运行时数据库已断开连接.如果您有一个应用程序生命周期的单个对象上下文,您将如何从中恢复?对它们进行批处理很好但是在应用程序的生命周期内保留一个很少是正确的解决方案. (2认同)
  • @Akash,"每次上下文初始化时加载元数据"都不是真的.它实际上是缓存的."实体框架自动缓存应用程序域中所需的元数据和其他信息,ADO.NET汇集数据库连接,因此每次重新创建上下文都是一种快速操作." (2认同)