将SQL查询转换为LINQ查询

3

这是需要转换为LINQ查询的SQL查询。

SELECT  pq.DocumentQueueID, 
    pq.DocumentQueueName, 
    pq.DepartmentName, 
    pq.UserLocation,
    ISNULL(T.DocumentCount, 0) DocCount, 
    ISNULL(CONVERT(VARCHAR(50),T.OldestDocumentDate),'') IngestionDateTime,
    ISNULL(B.UserName, '') UserName
FROM [dbo].[listPLDQueues] pq 
LEFT OUTER JOIN 
(
    SELECT dds.CurrentDocumentQueue, 
    SUM(dds.ImportPageCount) as DocumentCount, 
    MIN(dds.IngestionDateTime) as OldestDocumentDate
    FROM [dbo].[dataDocumentStats] dds
    GROUP BY dds.CurrentDocumentQueue
) AS T ON T.CurrentDocumentQueue = pq.DocumentQueueID
LEFT OUTER JOIN
(   SELECT duq.DocumentQueueID, UserName = 
    STUFF((SELECT ', ' + uq.UserDisplayName
    FROM [dbo].[dataUserQueues] uq
    WHERE uq.DocumentQueueID = duq.DocumentQueueID
    FOR XML PATH('')),1,2,'')
 FROM [dbo].[dataUserQueues] duq
 GROUP BY duq.DocumentQueueID
 ) AS B ON B.DocumentQueueID = pq.DocumentQueueID 
WHERE UPPER(WorkflowType) = 'INDEXING'

到目前为止,在LINQ查询中我已经完成了以下工作:

 var indexSummary = _eimStatsDB.listPLDQueues
          .Join(_eimStatsDB.dataDocumentStats,
              pld => pld.DocumentQueueID,
              dds => dds.CurrentDocumentQueue,
              (pld, dds) => new { pldQueues = pld, dataDocument = dds })            
          .Where(a => a.pldQueues.WorkflowType.ToLower() == "indexing")
          .GroupBy(a => a.pldQueues.DocumentQueueID)
          .ToList()
          .Select(a => new
          {
              DocumentQueueId = a.Key,
              DocumentQueueName = a.Select(i => i.pldQueues.DocumentQueueName).FirstOrDefault(),
              DepartmentName = a.Select(i => i.pldQueues.DepartmentName).FirstOrDefault(),
              DocumentCount = a.Sum(i => i.dataDocument.ImportPageCount),
              OldestDocumentDate = a.Min(i => i.dataDocument.IngestionDateTime),
              UserLocation = a.Select(i => i.pldQueues.UserLocation).FirstOrDefault(),
              IsChecked = false
          });

        var userNames = _eimStatsDB.dataUserQueues
            .GroupBy(e => e.DocumentQueueID)
            .ToList()
            .Select(e => new
            {
                DocumentId = e.Key,
                UserName = string.Join(",", e.Select(i => i.UserDisplayName))
            });

        var listPLDQueue = from pldqueue in _eimStatsDB.listPLDQueues
                           where pldqueue.WorkflowType == "Indexing"
                           select pldqueue;

        var result = from pldqueue in listPLDQueue
                     join iS in indexSummary
                     on pldqueue.DocumentQueueID equals iS.DocumentQueueId into pldjoin
                     from pld in pldjoin.DefaultIfEmpty()
                     join un in userNames
                     on pld.DocumentQueueId equals un.DocumentId into gj
                     from subuser in gj.DefaultIfEmpty()
                     select new
                     {
                         DocumentQueueId = pld.DocumentQueueId,
                         DocumentQueueName = pld.DocumentQueueName,
                         DepartmentName = pld.DepartmentName,
                         DocumentCount = (pld.DocumentCount == null ? 0 : pld.DocumentCount),
                         OldestDocumentDate = (pld.OldestDocumentDate == null? Convert.ToDateTime(string.Empty) : pld.OldestDocumentDate),
                         UserLocation = pld.UserLocation,
                         IsChecked = pld.IsChecked,
                         Usernames = (subuser == null ? string.Empty : subuser.UserName)
                     };

最后一个返回结果的查询出现了错误: “无法创建类型为'Anonymous type'的常量值。在此上下文中,仅支持基元类型或枚举类型。” 有没有更好的方法可以将所有不同的LINQ查询组合在一起?

错误出现在哪一行?我认为问题与您的连接查询有关,当分配“result”时。 - Tetsuya Yamamoto
是的,那个错误就在赋值结果时。我无法弄清楚它是什么。 - Nirav Parmar
您正在尝试将存储在内存中的集合与数据库对象连接起来,这会引发NotSupportedException异常。在Select语句之前尝试从userNames声明中删除ToList()方法,因为EF只能引用IEnumerable类型参数为任何基元类型(例如int)的连接,但是您可以使用IQueryable来实现。 - Tetsuya Yamamoto
1个回答

1

在检查了整个查询结构后,我发现除了listPLDQueue之外,另外两个join来源都是使用匿名类型参数的IEnumerable集合,而Entity Framework只能将IEnumerable与基元类型作为类型参数或在执行联接操作时使用IQueryable进行引用。

尝试删除或注释掉所有的ToList()方法,以便为indexSummaryuserNames分配IQueryable,然后考虑使用适当的类名称来代替使用匿名类型,如下所示:

var indexSummary = _eimStatsDB.listPLDQueues
          .Join(_eimStatsDB.dataDocumentStats,
              pld => pld.DocumentQueueID,
              dds => dds.CurrentDocumentQueue,
              (pld, dds) => new { pldQueues = pld, dataDocument = dds })            
          .Where(a => a.pldQueues.WorkflowType.ToLower() == "indexing")
          .GroupBy(a => a.pldQueues.DocumentQueueID)
        //.ToList() --> this converts IQueryable to IEnumerable, which should be dropped
          .Select(a => new listPLDQueues() // change this assignment to your model class name
          {
              DocumentQueueId = a.Key,
              DocumentQueueName = a.Select(i => i.pldQueues.DocumentQueueName).FirstOrDefault(),
              DepartmentName = a.Select(i => i.pldQueues.DepartmentName).FirstOrDefault(),
              DocumentCount = a.Sum(i => i.dataDocument.ImportPageCount),
              OldestDocumentDate = a.Min(i => i.dataDocument.IngestionDateTime),
              UserLocation = a.Select(i => i.pldQueues.UserLocation).FirstOrDefault(),
              IsChecked = false
          });

var userNames = _eimStatsDB.dataUserQueues
            .GroupBy(e => e.DocumentQueueID)
          //.ToList() --> this converts IQueryable to IEnumerable, which should be dropped
            .Select(e => new dataUserQueues() // change this assignment to your model class name
            {
                DocumentId = e.Key,
                UserName = string.Join(",", e.Select(i => i.UserDisplayName))
            });

每个作业将返回 IQueryable<T>(其中 T 分配给 DB 模型类名,例如 IQueryable<listPLDQueues>IQueryable<dataUserQueues>),适合在包含 join 查询的 result 赋值中使用它们。
相关问题和参考:

无法创建类型为“匿名类型”的常量值。只支持原始类型或枚举类型

无法创建类型为“匿名类型”的常量值。只支持原始类型或枚举类型两个 db Linq 查询

用于匿名类型的 IQueryable


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接