实体框架性能缓慢

时间:2016-11-10 11:03:25

标签: c# performance entity-framework entity-framework-6

我们正在使用EF 6.0,.NET 4.5并使用代码优先方法,我们的数据库有大约170个实体(表),主表包含大约150,000条记录 在第一次加载实体框架时,它需要大约25秒。 我试图改善这个时间,因为这太慢了,随着记录数量的增加,它变得越来越慢。 我尝试过生成原生图像,尝试使用预先生成的交互式视图,但我无法取得任何重大改进。

有人可以帮我吗?

感谢。

4 个答案:

答案 0 :(得分:1)

您可以考虑实体框架预生成的映射视图。您可以使用 EF Power Tools 创建预生成视图。

  

使用预生成的视图可以降低模型生成视图的成本   加载(运行时)到编译时。虽然这改善了启动   在运行时的性能,你仍然会经历视图的痛苦   你正在发展的那一代。还有几个   这些技巧可以帮助降低视图生成的成本   编译时间和运行时间。

enter image description here

您可以参考此内容了解更多相关信息:Entity Framework Pre-Generated Mapping Views

您可以在实体框架中使用缓存来提高应用的效果。

有三种类型的缓存。

<强> 1。对象缓存 - ObjectConManager内置的ObjectStateManager     实例在内存中跟踪已经存在的对象     使用该实例检索。这也称为第一级     高速缓存中。

<强> 2。查询计划缓存 - 在a时重用生成的store命令     查询执行多次。

第3。元数据缓存 - 跨不同的模型共享模型的元数据    与同一模型的连接。

您可以参阅此文章以了解有关它的更多信息:Performance Considerations for EF 6

答案 1 :(得分:1)

我最近有一个简单的查询,它在SSMS中运行速度非常快,在我的C#程序中使用实体框架运行的时间太长了。

在解决EF性能问题时,此页面非常有用:

https://www.simple-talk.com/dotnet/net-tools/entity-framework-performance-and-what-you-can-do-about-it/

..但在这种情况下,没有任何帮助。所以最后,我这样做了:

        List<UpcPrintingProductModel> products = new List<UpcPrintingProductModel>();
        var sql = "select top 75 number, desc1, upccode "
                + "from MailOrderManager..STOCK s "
                + "where s.number like @puid + '%' "
        ;
        var connstring = ConfigurationManager.ConnectionStrings["MailOrderManagerContext"].ToString();
        using (var connection = new SqlConnection(connstring))
        using (var command = new SqlCommand(sql, connection)) {
            connection.Open();
            command.Parameters.AddWithValue("@puid", productNumber);
            using (SqlDataReader reader = command.ExecuteReader()) {
                while (reader.Read()) {
                    var product = new UpcPrintingProductModel() {
                        ProductNumber = Convert.ToString(reader["number"]),
                        Description = Convert.ToString(reader["desc1"]),
                        Upc = Convert.ToString(reader["upccode"])
                    };
                    products.Add(product);
                }
            }
        }

(对于这个特定的查询,我只是完全绕过了EF,并使用了旧的备用:System.Data.SqlClient。)

你可以厌恶地皱起鼻子;我当然做到了 - 但实际上并没有那么长的时间来写,而且它几乎立即执行。

答案 2 :(得分:0)

您还可以在应用程序启动时异步“加热” dbcontexts 来解决此问题。

protected void Application_Start()
 {
   // your code.
    // Warming up.
            Start(() =>
            {
                using (var dbContext = new SomeDbContext())
                { 
                    // Any request to db in current dbContext.
                    var response1 = dbContext.Addresses.Count();
                }
            });
 }

 private void Start(Action a)
 {
    a.BeginInvoke(null, null);
 }

我还建议使用以下设置:(如果它们适合您的应用)

  • dbContext.Configuration.AutoDetectChangesEnabled = false;                     dbContext.Configuration.LazyLoadingEnabled = false;                     dbContext.Configuration.ProxyCreationEnabled = false;

  • 跳过验证部分(即Database.SetInitializer<SomeDbContext>(null);

  • 在GET查询中使用 .asNoTraking()

有关其他信息,请参阅:

答案 3 :(得分:0)

在某些情况下,EF不使用查询计划缓存。例如,如果您使用contans,任何,所有方法或在查询中使用常量。您可以尝试NihFix.EfQueryCacheOptimizer。它将转换允许EF使用cahce的查询表达式。