使用MVC 4和实体框架6访问大型数据库的最佳方法是什么?

本文关键字:数据库 最佳 方法 是什么 大型 访问 MVC 实体 框架 使用 | 更新日期: 2023-09-27 18:02:32

我有一个用MVC 4和实体框架6编写的电子邮件营销web应用程序。该应用程序在web农场的sql数据库中存储了超过10K个电子邮件地址以及联系信息。

当数据库很小,只有几百条记录时,一切都很好。但是,当我完全填充数据库时,使用"Foreach"语句检索和写入每个单独的记录非常慢。对于某些操作,可能需要长达14分钟才能完成。我已经尽量减少我在任何时候处理的记录的数量,但这使应用程序变得笨拙。

我在想,有没有其他方法可以用来加快这个速度。也许SQL存储过程,或GitHub上的东西,将使它更容易。如果有,请告诉我在哪里可以了解更多。任何帮助都会很感激。以下是其中一个查询:

private int AddOrUpdateCampaigns(Campaign campaign
        , IEnumerable<AssignEmailContacts> assignEmailContacts)
{
    DataBaseContext db = new DataBaseContext();
    int TotalAssigned = 0;
    if (assignEmailContacts == null) return(TotalAssigned);
    if (campaign.CampaignId != 0)
    {   
      foreach (var emailContact 
                in assignEmailContacts.Where(a => a.Assigned == false))
      {   
        campaign.EmailContacts.Remove(
                db.EmailContacts.Find(emailContact.EmailContactId));
      }
      foreach (var emailContact 
                in assignEmailContacts.Where(a => a.Assigned))
      {                            
        campaign.EmailContacts.Add(
                db.EmailContacts.Find(emailContact.EmailContactId));
            TotalAssigned += 1;
      }
    }
    return (TotalAssigned);
}

使用MVC 4和实体框架6访问大型数据库的最佳方法是什么?

EF的缓慢之处在于,当您可以获得所需的所有数据时,却要进行大量的数据库往返。跟踪对象变化。考虑到这一点,您可以在EF中使用两个主要的性能工具:

  1. Include扩展方法。
  2. AsNoTracking扩展方法(只对读有用,但在中等规模的+数据集上有很大的性能提升,可能与Include冲突)。

第一个方法允许您在单个查询中拉下所有数据(提供对象图中没有继承)。第二个停止EF做所有的跟踪工作,这使得读取速度快得多。

当某些东西看起来很慢时,我通常做的是启动SQL Profiler,在我的数据库上运行跟踪,然后运行需要时间的方法。然后我添加包含,直到我减少到查询的最小数量。

还可以添加索引之类的。

还有一点。您的数据库可能是垃圾!如果一个数据库位于配置糟糕的服务器上,并且有许多其他活动数据库,那么性能问题可能仅仅是由于磁盘争用造成的。如果EF和索引调优效果不大,那么请查看一下服务器:硬件确实很重要。

在EF中更新多个数据库行很慢!

我假设有一个名为CampaignContacts的表,其中包含Campaign和Contacts的n对n关系的数据。幸运的是,EF6允许执行原始查询。

using System.Collections.Generic;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Text;
public class YourDbContext : DbContext
{
    public void DeleteBatchCampaignContacts(IList<int> ids)
    {
        if (ids == null) return;
        if (ids.Count == 0) return;         
        //ONLY because the parameter comes from a list of Int, else you might risk injection
        Database.ExecuteSqlCommand(string.Format("DELETE FROM CampainContacts WHERE CampaignId in ({0})", string.Join(",", ids)));
    }
    public void UpdateBatchCampaignContacts(int campaignId, IList<int> ids)
    {
        if (ids == null) return;
        if (ids.Count == 0) return;
        Database.ExecuteSqlCommand(string.Format("UPDATE CampaignContacts SET CampaignId = @campaignId WHERE EmailContactId in ({0})", string.Join(",", ids),
            new SqlParameter("@campaignId", campaignId)));
    }
}

注意代码重复。您可以重构这些函数,但这将比您当前的解决方案更快。您可以添加一些特性,例如以50个id为批量执行查询,以便处理数千个id更新。

在处理RDBM中的记录时,我通常使用存储过程,这样做的好处是执行速度更快。

可能只是可能是你可以加快你的查询哈希你的电子邮件作为ID,并根据这些参数做搜索,但取决于你的项目的阶段或阶段。

你也可以直接查询你的数据库,看看需要多长时间,然后你就知道这是不是你的代码