Linq查询 - 多个连接并选择2列

时间:2016-08-30 22:19:39

标签: c# entity-framework linq

我正在使用Entity Framework来处理我的数据库,我需要帮助形成一个LINQ查询,它将帮助我获取列LoginId和AccNumber。我每个AccNumber只需要1个LoginId,无论是哪个LoginId都无关紧要。就目前而言,大约有800K LoginIds和5000 AccNumber。因此,最后我需要1个与1个LoginId相关联的AccNumber。所以我应该有5000行和2列。

以下是我需要加入的表格:

项目

ItemId,AccNumber,其他不相关的列

Block_Item

ItemId,BlockId,其他不相关的列

Bookversion_Block

BookversionId,BlockId,其他不相关的列

Sudent

LoginId,BookversionId,其他不相关的列

理想情况下,我想使用LINQ复制此SQL查询(只是尝试提供尽可能多的信息)

select
LoginId,
AccessionNumber
from Item I
outer apply (select top 1 * from Block_Item where I.ItemId = ItemId) BI
outer apply (select top 1 * from BookletVersion_Block where BlockId = BI.BlockId) BVB
outer apply (select top 1 LoginId from Student where BookletVersionId = BVB.BookletVersionId) ST

这是我尝试的,然而,我得到的结果不正确,我回来了183,000条记录,执行此操作需要10分钟。这一行“var uniques = q.ToList();”是一个需要很长时间的人。

using (var context = new MyContext())
{
    context.Database.CommandTimeout = 1200;
    var listOfAccessionNumbers = GetListOfAllAccessionNumbers(context);

    var q = (from items in context.Items
             join blockItem in context.Block_Item
             on items.ItemId equals blockItem.ItemId into bi

             join bookletVersion in context.BookletVersion_Block
             on bi.Select(x => x.BlockId).FirstOrDefault() equals bookletVersion.BlockId into BVB

             join student in context.Students
             on BVB.Select(x => x.BookletVersionId).FirstOrDefault() equals student.BookletVersionId into st

             //'VH098334'
             select new { LoginId = st.Select(x => x.LoginId).FirstOrDefault().ToString(),
             AccNum = items.AccessionNumber.ToString() });

     **var uniques = q.ToList();**

     IList<string> listOfLogins = new List<string>();
     foreach (var accessionNumber in listOfAccessionNumbers)
     {
         var i = q.ToList().Find(x => x.AccNum.Contains(accessionNumber));
         listOfLogins.Add(i.LoginId);
     }
}

1 个答案:

答案 0 :(得分:0)

尝试分离你的linq操作,希望看到哪一个占用时间最长以及哪里出错。

另外,我建议使用带有accNumber作为键的字典和作为值的LoginID,这样您就可以确保每个accNumber与1和只有1个LoginID相关联。

Dictionary<string, string> uniques = new Dictionary<string, string>();
var q = (from items in context.Items
         join bi in context.Block_Item
         on items.ItemId equals bi.ItemId
         select items).ToList();

//var first = bi.Select(x => x.BlockId).FirstOrDefault();
var val = (from b in context.BookletVersion_Block.Select(bv => bv.BlockId)
           join a in q on b equals q.FirstOrDefault().BlockId into BVB
           join c in context.Students on BVB.FirstOrDefault().BookletVersionId equals c.BookletVersionId into st
           select new { LoginId = st.Select(x => x.LoginId).FirstOrDefault().ToString(), AccNum = a.AccessionNumber.ToString() });

//if (!uniques.ContainsKey(bi.AccNum))
    //uniques.Add(val.AccNum, val.LoginId);

uniques = val.ToDictionary(c => c.AccNum, c => c.LoginId);

Haven没有测试过,所以让我知道所花的时间以及你是否得到正确的值。

字典应该确保你得到5000个值,但是我不确定它为什么花了这么长时间,但是先让我们修复记录数量问题。