微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

LINQ使用字符串格式

如何解决LINQ使用字符串格式

我遇到关于LINQ to Entities does not recognize the method 'System.String Format错误,但是过去我可以在包含.AsEnumerable()的情况下执行此操作,因为GroupBy部分需要做一些不同的事情?

select new PresentationLayer.Models.PanelMeeting
    {
    GroupId = pg.GroupId,MeetingId = pmd.MeetingId,GuidelineName = pmv.GuidelineName,PaneldisclosuresAttendanceURL = string.Format("{0}?MeetingId={1}&GroupId=0",PaneldisclosureLink,pmd.MeetingId),}).GroupBy(g => new
    {
        g.MeetingId,g.GroupId
    })
    .AsEnumerable()
    .SelectMany(grp => grp.AsEnumerable()).ToList(),

解决方法

如果要使用string.Format,首先必须从服务器获取数据。 您可以将.GroupBy( ... ),然后将.AsEnumerable()调用移到顶部,然后移到select new PresentationLayer.Models.PanelMeeting { ... }之前。如果您不是那样选择太多数据的话...

,

您必须了解IEnumerable<...>IQueryable<...>之间的区别。

IEnumerable

实现IEnumerable<...>的对象表示一系列相似的项。您可以要求序列中的第一个元素,只要您有元素,就可以要求下一个元素。 IEnumerable对象应该在自己的进程中执行。 IEnumerable对象包含一切以枚举序列。

在最低级别,使用GetEnumerator() / MoveNext() / Current完成此操作:

IEnumerable<Customer> customers = ...
IEnumerator<Customer> enumerator = customers.GetEnumerator();
while (enumerator.MoveNext())
{
    // There is a next Customer
    Customer customer = enumerator.Current;
    ProcessCustomer(customer);
}

如果使用foreach,则在内部调用GetEnumerator / MoveNext / Current。

如果您仔细观察LINQ,您会发现有两组LINQ方法。返回IEnumerable<TResult>的那些和不返回IEnumerable<...>的那些

第一组中的

LINQ函数不会枚举查询。他们使用延迟执行或延迟执行。在每种LINQ方法的注释部分,您将找到此描述。

另一组的LINQ函数将执行查询。如果查看reference source of extension class Enumerable,您会发现它们在内部使用foreach,或者在较低级别使用GetEnumerator / MoveNext / Current

IQueryable

实现IQueryable<...>的对象看起来像IEnumerable。但是,它表示获取可枚举序列数据的潜力。数据通常由不同的过程提供。

为此,IQueryable拥有一个Expression和一个Provider。表达式表示必须以某种通用格式获取的内容。提供者知道谁将提供数据(通常是数据库管理系统)以及如何与该DBMS通信(通常是SQL)。

当您开始枚举序列时,使用GetEnumerator深入内部,则将表达式发送给提供程序,该提供程序将尝试将其转换为SQL。从DBMS提取数据,并将其作为Enumerable对象返回。通过重复调用MoveNext / Current来访问获取的数据。

由于在开始枚举之前未与数据库联系,因此必须保持与数据库的连接处于打开状态,直到完成枚举为止。您可能曾经犯过以下错误:

IQueryable<Customer> customers;
using (var dbContext = new OrderDbContext(...))
{
    customers = dbContext.Customers.Where(customer => customer...);
}
var fetchedCustomers = customers.ToList();

回到您的问题

在查询中,您使用string.Format(...)。您的提供程序不知道如何将此方法转换为SQL。您的提供者也不知道您的任何本地方法。实际上,LINQ对实体甚至不支持几种标准的LINQ方法。参见Supported and Unsupported LINQ methods

如何解决问题?

如果需要调用不受支持的方法,则可以使用AsEnumerable来获取数据。 AsEnumerable之后的所有LINQ方法都由您自己的进程执行。因此,您可以调用任何自己的函数。

数据库管理系统在表处理方面进行了优化。数据库查询的最慢部分之一是将所选数据传输到本地进程。因此,让DBMS进行所有选择,并尝试传输尽可能少的数据。

因此,让您的DBMS执行Where /(组-)加入/求和/ FirstOrDefault /任何其他操作。字符串格式设置最适合您。

在您的String.Format中,使用PanelDisclosureLink和pmd.MeetingId。如果您的进程进行格式化,可能会更快。 las,您忘记给我们开始或提出疑问。

我不确定您的PanelDisclosureLink来自何处。它是局部变量吗?如果是这种情况,那么PanelDisclosuresAttendanceURL将是组中每个项目的相同字符串。这是故意的吗?

var panelDisclosureLine = ...;

var result = dbContext... // probably some joining with Pgs,Pmds and Pmvs,.Select(... => new
    {
        GroupId = pg.GroupId,MeetingId = pmd.MeetingId,GuidelineName = pmv.GuidelineName,})

    // make groups with same combinations of [MeetingId,GroupId]
    .GroupBy(joinResult => new 
        {
            MeetingId = joinResult.MeetingId,GroupId = joinResult.GroupId,},// parameter resultSelector: use the Key,and all JoinResult items that have this key
        // to make one new:
        (key,joinResultItemsWithThisKey) => new
        {
            MeetingId = key.MeetingId,GroupId = key.GroupId,GuideLineNames = joinResultsItemsWithThisKey
                .Select(joinResultItem => joinResultItem.GuideLineName)
                .ToList(),})

因此,到目前为止,DBMS已将您的联接结果转换为具有 [MeetingId,GroupId]组合以及已属于的所有GuideLineName的列表 此[MeetingId,GroupId]组合。

现在,您可以将其移至本地进程并使用String.Format。

.AsEnumerable()
.SelectMany (fetchedItem => fetchedItem.GuideLineNames,(fetchedItem,guideLineName) => PresentationLayer.Models.PanelMeeting
    {
        GroupId = fetchedItem.GroupId,MeetingId = fetchedItem.MeetingId,GuidelineName = guidelineName,PanelDisclosuresAttendanceURL = string.Format("...",PanelDisclosureLink,fetchedItem.MeetingId);

注意:在我的参数选择中,复数是集合;单数是这些集合的元素。

        PanelDisclosuresAttendanceURL = string.Format("{0}?MeetingId={1}&GroupId=0",pmd.MeetingId),}).
    .GroupBy

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。