3

我有一个 Linq 查询。当我运行查询时,只有 10 条记录需要 13 秒才能将数据提取到模型中。我需要知道我写的查询是否对性能有好处。请指导我做错了什么。

代码

    var stocktakelist = (from a in Db.Stocktakes
                             select new ExportStock
                                 {
                                     Id = a.Id,
                                     ItemNo = a.ItemNo,
                                     AdminId = (from admin in Db.AdminAccounts where admin.Id == a.Id select admin.Name).FirstOrDefault(),
                                     CreatedOn = a.CreatedOn,
                                     Status = (from items in Db.Items where items.ItemNo == a.ItemNo select items.ItemStatu.Description).FirstOrDefault(),
                                     Title = (from tit in Db.BibContents where tit.BibId == (from bibs in Db.Items where bibs.ItemNo == a.ItemNo select bibs.BibId).FirstOrDefault() && tit.TagNo == "245" && tit.Sfld == "a" select tit.Value).FirstOrDefault()   // This line of Query only makes the performance Issue
                                 }
            ).ToList();

谢谢

4

4 回答 4

2

之所以这么慢,是因为它为外部 LINQ 语句中的每个项目运行 3 个内部 LINQ 语句。使用 LINQ 连接将只运行 4 个查询,然后将它们链接在一起,这样更快。

要了解如何加入,Internet 上有大量资源,具体取决于您使用的 LINQ 类型。

如果您从 SQL 服务器检索这些数据,或许可以考虑在 SQL 中进行这项密集工作——这就是 SQL 的设计目的,它比 .NET 快得多。编辑:如下所示,如果使用 LINQ to SQL/Entities 并使用正确的连接语法,则工作是在 SQL 中完成的。

于 2013-01-04T13:20:03.577 回答
1

正如其他人所说,您应该在 LINQ 中使用左外连接,就像在 SQL 中编写它一样。

转换后,您上面的查询最终看起来大致像这样(未经测试,但给出了基本想法):

var a = from a in Db.Stocktakes
    join admin in Db.AdminAccounts on admin.Id equals a.Id into tmpAdmin
    from ad in tmpAdmin.DefaultIfEmpty()
    join item in Db.Items on item.ItemNo equals a.ItemNo into tmpItem

    from it in tmpItem.DefaultIfEmpty()
    join title in Db.BibContents on bib.BibId equals items.BibId into tmpTitle

    from ti in tmpTitle.DefaultIfEmpty()
    where ti.TagNo == "245" 
        && ti.Sfld == "a"
    select new ExportStock
    {
        Id = a.Id,
        ItemNo = a.ItemNo,
        AdminId = ad == null ? default(int?) : ad.Id,
        CreatedOn = a.CreatedOn,
        Status = it == null ? default(string) : it.ItemStatus.Description,
        Title = ti == null ? default(string) : ti.Value
    };
于 2013-01-04T13:30:53.170 回答
1

我试图用一些连接来创建相应的查询以供练习。我无法对其进行测试,也不能 100% 确定此查询是否会得到您希望的结果,但也许至少它会提示您如何使用 linq 编写联接。

from a in Db.Stocktakes

join admin in Db.AdminAccounts
  on a.Id equals admin.Id
into adminJoinData
from adminJoinRecord in adminJoinData.DefaultIfEmpty( )

join items in Db.Items
  on a.ItemNo equals items.ItemNo
into itemsJoinData
from itemsJoinRecord in itemsJoinData.DefaultIfEmpty( )

join title in Db.BibContents
   (
       from subQuery in Db.BibContents
       where subQuery.TagNo == "245"
       where subQuery.Sfld == "a"
       select subquery
   )
  on title.BibId equals itemsJoinRecord.BidId
into titleJoinData
from titleJoinRecord in titleJoinData.DefaultIfEmpty( )

select new ExportStock( )
{
    Id = a.Id,
    ItemNo = a.ItemNo,
    AdminId = adminJoinRecord.Name,
    CreatedOn = a.CreatedOn,
    Status = itemsJoinRecord.ImemStatu.Description,
    Title = titleJoinRecord.Value
}
于 2013-01-04T13:33:42.537 回答
0

使用 lambda 表达式,您的查询将如下所示:

        Db.Stocktakes
            .Join(Db.AdminAccounts, a => a.Id, b => b.Id, (a,b) => new { a, AdminId = b.Name })
            .Join(Db.Items, a => a.ItemNo, b => b.ItemNo, (a,b) => new { a, Status = b.ItemStatus.Description, BidId = b.BibId })
            .Join(Db.BibContents, a => a.BibId, b => b.BibId, (a,b) => new { a, Value = b.Value, TagNo = b.TagNo, Sfld = b.Sfld })
            .Where(a => a.TagNo == "245" && a.Sfld == "a")
            .Select(a => 
                new ExportStock { Id = a.Id, 
                                  ItemNo = a.ItemNo,
                                  AdminId = a.AdminId,
                                  CreatedOn = a.CreatedOn,
                                  Status = a.Status,
                                  Title = a.Value
                }
            ).ToList();
于 2013-01-04T13:51:32.620 回答