C#使用LINQ to Entities比较来自两个独立数据库的数据列表

时间:2013-05-08 00:16:09

标签: entity-framework c#-4.0

我有2个SQL Server数据库,托管在两个不同的服务器上。我需要从第一个数据库中提取数据。这将是一个整数列表。然后我需要将此列表与第二个数据库中多个表中的数据进行比较。根据某些条件,我需要在第二个数据库中更新或插入一些记录。

我的解决方案: (使用LINQ to Entities的WCF服务/实体框架)

  1. 从第1个db获取整数列表,不到一秒钟获取20,942个记录
  2. 我使用以下查询使用整数列表与第二个数据库中的表进行比较:
  3. 
        List<int> pastDueAccts; //Assuming this is the list from Step#1
        var matchedAccts = from acct in context.AmAccounts
                           where pastDueAccts.Contains(acct.ARNumber)
                           select acct;
    
    

    上面的查询花了很长时间才发出超时错误。尽管AmAccount表只有大约400条记录。

    1. 获得这些匹配的协议后,我需要在第二个数据库的单独表中更新或插入记录。
    2. 有人可以帮助我,我怎样才能更有效地完成第二步?我认为Contains函数使它变慢。我也试过暴力,通过一个foreach循环,我一次提取一个记录并进行比较。仍然需要太长时间并给出超时错误。数据库服务器仅显示已使用的内存的30%。

2 个答案:

答案 0 :(得分:0)

使用SQL事件探查器配置发送到数据库的sql查询。捕获发送到数据库的SQL语句并在SSMS中运行它。您应该能够捕获Entity Framework强加的开销。你可以在你的问题中粘贴步骤#2中发出的SQL语句吗?

答案 1 :(得分:0)

查询本身将包含所有20,942个整数。

如果你的AmAccount表总是有这么多的记录,你可以只返回ARNumber的整个列表,将它们与列表进行比较,然后具体说明哪些记录到返回:

List<int> pastDueAccts; //Assuming this is the list from Step#1
List<int> amAcctNumbers = from acct in context.AmAccounts
                          select acct.ARNumber

//Get a list of integers that are in both lists
var pastDueAmAcctNumbers = pastDueAccts.Intersect(amAcctNumbers);

var pastDueAmAccts = from acct in context.AmAccounts
                     where pastDueAmAcctNumbers.Contains(acct.ARNumber)
                     select acct;

您仍然需要担心您为该查询提供了多少ID,并且您最终可能需要批量检索它们。

<强>更新

希望有人有一个比这更好的答案,但是有这么多的记录并且纯粹在EF中这样做,你可以像我之前所说的那样尝试批处理:

//Suggest disabling auto detect changes
//Otherwise you will probably have some serious memory issues
//With 2MM+ records
context.Configuration.AutoDetectChangesEnabled = false;

List<int> pastDueAccts; //Assuming this is the list from Step#1

const int batchSize = 100;

for (int i = 0; i < pastDueAccts.Count; i += batchSize)
{
    var batch = pastDueAccts.GetRange(i, batchSize);

    var pastDueAmAccts = from acct in context.AmAccounts
                         where batch.Contains(acct.ARNumber)
                         select acct;
}