使用MVC 4和Entity Framework 6访问大型数据库的最佳方法是什么

时间:2014-05-08 20:14:08

标签: c# sql asp.net-mvc entity-framework

我有一个用MVC 4和Entity Framework 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);
}

3 个答案:

答案 0 :(得分:3)

当您可以获得所需的所有数据时,关于EF的慢点就是在数据库中进行大量往返;跟踪对象更改。考虑到这一点,您可以在EF中使用两种主要的性能工具:

  1. Include扩展方法。
  2. AsNoTracking扩展方法(仅对读取有用,但对中型+数据集有很大的性能提升,可能与Include冲突。)
  3. 第一种方法允许您在单个查询中下拉所有数据(假设对象图中没有继承)。第二次阻止EF执行所有跟踪操作,这使得读取速度更快。

    当看起来很慢时,我通常会做的事情是SQL Profiler,在我的数据库上运行跟踪,然后运行花费时间的方法。然后我添加包含,直到我查询到最少数量的查询。

    还记得你可以添加索引等。

    还有一件事。你的数据库可能是垃圾!如果您在配置错误的服务器上有许多其他活动数据库的数据库,那么性能问题可能仅仅是由于磁盘争用。如果EF和索引调整影响不大,请看一下服务器:硬件真的很重要。

答案 1 :(得分:1)

在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更新。这是一个开始。

答案 2 :(得分:0)

在处理RDBM中的记录时,我通常会使用存储过程,您将拥有更快执行的优势。

可能只是你可以通过将你的电子邮件作为ID散列来加速你的查询,并根据这些参数进行搜索,但取决于项目的阶段或阶段。

您还可以直接查询您的数据库并查看需要多长时间,然后您就知道它是否是您的代码

相关问题