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

时间:2011-04-04 02:08:43

标签: c# linq-to-sql entity-framework sql-server-ce code-first

我最近更新了一个使用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; }
}

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

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

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

4 个答案:

答案 0 :(得分:5)

  

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

这不是必需的......

  1. Entity Framework的默认架构已经实现了存储库模式。
  2. 保持ObjectContext存活并不意味着您保持与数据库的连接。
  3. 仅当您从数据库加载或保存更改时,才会获取连接池中的新连接并执行操作。
  4. 当然,使用block会减慢因为每个使用块都会执行以下操作,

    1. 初始化上下文(需要从资源加载元数据)
    2. 验证一些事情
    3. 打开与DB的连接
    4. 执行您的任务
    5. 清理并关闭数据库
    6. 现在前两个步骤确实需要花费大量时间,并且您的应用中将有多个相同类型的对象在一段时间内存活更长时间,因为每个新上下文都会为每个查询创建相同对象的新副本。

      实体框架已经实现了身份映射,这意味着它将使对象保持活动状态,并且在整个上下文生命周期内只保留同一主键的一个对象副本,这不仅可以节省内存,而且还可以更快地执行。

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

答案 1 :(得分:1)

答案 2 :(得分:0)

阅读有关实体框架内部工作的herehere。它与EFv4和ObjectContext API有关,但带有DbContext API的EFv4.1只是EFv4的包装。

如果您觉得查询速度很慢,请尝试在相同的上下文中执行两次,并在上下文的不同实例上执行两次。第一个测试将检查问题是否在对象实现中,因为对象将仅针对第一个查询实现,第二个测试将检查上下文初始化是否存在任何问题(如果您使用标准上下文创建连接,则不会发生这种情况字符串)。

将执行与编译查询进行比较也很有趣,但我觉得编译的查询不是DbContext API的一部分。

答案 3 :(得分:0)

当您更改为Code First方法时,是否更改了数据库的结构?

我的猜测是肯定的,这是造成性能变化的原因。

我也注意到你班上的事情,你有:

public int TrialDefinitionId { get; set; }

public virtual TrialDefinition TrialDefinition { get; set; }

这些都需要吗?