Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在LINQ中使用DBFunction?_C#_Linq To Entities_Dbfunctions - Fatal编程技术网

C# 如何在LINQ中使用DBFunction?

C# 如何在LINQ中使用DBFunction?,c#,linq-to-entities,dbfunctions,C#,Linq To Entities,Dbfunctions,我有一个LINQ to实体: var result = (from inspArch in inspectionArchives from inspAuth in inspArch.InspectionAuthority group new { inspArch, inspAuth } by inspArch.CustomerId into g select new {

我有一个LINQ to实体:

var result = (from inspArch in inspectionArchives
              from inspAuth in inspArch.InspectionAuthority
              group new { inspArch, inspAuth } by inspArch.CustomerId into g
              select new
              {
                  clientId = g.Key,
                  id = g.Select(x => x.inspArch.Id).ToArray(),               
                  authId = g.Select(x => x.inspAuth.Id).Distinct().ToArray()
              });
但在运行时,我得到以下错误:

"LINQ to Entities does not recognize the method 'Int32[] ToArray[Int32](System.Collections.Generic.IEnumerable`1[System.Int32])' method, and this method cannot be translated into a store expression."
我知道我可以这样写我的LINQ:

var result = (from inspArch in inspectionArchives
              from inspAuth in inspArch.InspectionAuthority
              group new { inspArch, inspAuth } by inspArch.CustomerId into g
              select new
              {
                  clientId = g.Key,
                  id = g.Select(x => x.inspArch.Id),    
                  authId = g.Select(x => x.inspAuth.Id).Distinct()
              }).ToList(); 
然后:

var result2 = (from res in result
               select new
               {
                   clientId = res.clientId,
                   id = res.id.ToArray(),
                   authId = res.authId.ToArray()
               });
它工作得很好,但是,它将整个表拉入内存,然后应用投影,这不是很有效

所以我读到了,;有没有办法在这些行上使用提到的DbFunctions类

id = g.Select(x => x.inspArch.Id).ToArray(),               
authId = g.Select(x => x.inspAuth.Id).Distinct().ToArray()

取而代之的是ToArray()方法,或者是另一种使ToArray()方法可被LINQ识别为实体的方法?

你太接近了。这里没有与
DbFunctions
相关的内容,您只需要说明查询具体化是如何工作的

因此,让我们从查询开始,删除
ToArray()
stuff:

var query = (from inspArch in inspectionArchives
             from inspAuth in inspArch.InspectionAuthority
             group new { inspArch, inspAuth } by inspArch.CustomerId into g
             select new
             {
                 clientId = g.Key,
                 id = g.Select(x => x.inspArch.Id),               
                 authId = g.Select(x => x.inspAuth.Id).Distinct()
             });
如果放置断点,您将看到这是一个db sql查询,也可以通过以下方式看到:

var sqlQuery = query.ToString();
现在唯一剩下的事情是如何通过这些
ToArray()
调用实现最终投影。从逻辑上讲,第一次尝试是:

var result = query
    .Select(e => new { e.clientId, id = e.Id.ToArray(), authId = e.authId.ToArray() })
    .ToList();
但结果将是相同的例外,因为EF Linq提供者足够聪明,能够完成所有的预测并生成最终的预测

因此,在进行最终投影之前,我们需要将查询具体化不要为此使用
ToList()
ToArray()
!最便宜的方法是使用
ToEnumerable()
它将为我们提供一个最小(单个项目)的临时投影内存对象,然后我们将其转换为最终投影

因此,我们的最终(和有效)代码将是:

var result = query
    .AsEnumerable()
    .Select(e => new { e.clientId, id = e.Id.ToArray(), authId = e.authId.ToArray() })
    .ToList();
或者把它们放在一起:

var result =
    (from inspArch in inspectionArchives
     from inspAuth in inspArch.InspectionAuthority
     group new { inspArch, inspAuth } by inspArch.CustomerId into g
     select new
     {
          clientId = g.Key,
          id = g.Select(x => x.inspArch.Id),               
          authId = g.Select(x => x.inspAuth.Id).Distinct()
     })
    .AsEnumerable()
    .Select(e => new { e.clientId, id = e.Id.ToArray(), authId = e.authId.ToArray() })
    .ToList();
p.S.处理EF查询时,最好不要在投影中使用
ToArray()。最终使用
ToList()
或让它们保持原样(
IEnumerable
IORDerenumerable
等)-EF将使用最合适的容器为您具体化它们(通常是列表,这就是为什么
ToList()
被识别,而
ToArray()
不被识别的原因)。

它工作正常,但是,它将整个表格拉入内存,然后应用投影…不是很有效。-您是否通过分析进出数据库的流量来验证这一点?在
.ToList()
之前的每个部分(包括投影)都被转换为SQL。也许你的意思是说,
ToList
在内存中构建了一个实际上并不需要的结果?如果是这样,只需使用
AsEnumerable()
即可防止这种情况。为什么在最终结果中使用数组如此重要?