关于asp.net mvc:为什么LINQ to Entities无法识别方法’System.String ToString()?

Why LINQ to Entities does not recognize the method 'System.String ToString()?

在MVC3 Web应用程序中获取错误。LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression.

当我尝试从查询中使用ef获取值时:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class DataRepository
    {
        public mydataEntities1 dbContext = new mydataEntities1();

        public List<SelectListItem> GetPricingSecurityID()
        {
        var pricingSecurityID = (from m in dbContext.Reporting_DailyNAV_Pricing
                                     select new SelectListItem
                                         {
                                                Text = m.PricingSecurityID.ToString(),
                                                Value = m.PricingSecurityID.ToString()
                                         });

        return pricingSecurityID.ToList();
        }
    }

无法转换为SQL。我想,从理论上讲,它是可以实现的,但还没有实现。

您只需在获得结果后执行投影:

1
2
3
var pricingSecurityID = (from m in dbContext.Reporting_DailyNAV_Pricing
                                     select m.PricingSecurityID).AsEnumerable()
    .Select(x => new SelectListItem{ Text = x.ToString(), Value = x.ToString() });


如果它已经是一个字符串,那么为什么你一开始就打电话给ToString?我怀疑linq to实体中没有包含翻译,因为它是没有意义的。将select子句更改为:

1
2
3
4
5
select new SelectListItem
{
    Text = m.PricingSecurityID,
    Value = m.PricingSecurityID
}

如果您确实需要执行Linq to Entities不支持的操作,请使用AsEnumerable将数据库查询转换为进程中查询:

1
2
3
4
5
6
7
8
9
public List<SelectListItem> GetPricingSecurityID()
{
    return dbContext.Reporting_DailyNAV_Pricing
                    .Select(m => m.PricingSecurityID)
                    .AsEnumerable() // Rest of query is local
                    // Add calls to ToString() if you really need them...
                    .Select(id => new SelectListItem { Text = id, Value = id })
                    .ToList();
}

我也同意杰森的反对意见,顺便说一句,你最好还是退回其他地方提供的List

还要注意,如果只使用一个select子句或只是一个where子句,查询表达式实际上不会添加太多内容—调用LINQ扩展方法可能会减少混乱,特别是如果要调用查询表达式(如ToList中不支持的方法)中不支持的方法。


这个怎么样?在本例中,db中的vdn字段和skill字段都是整数。我在寻找两个领域的匹配,所以我有两个比较。

包括:

1
using System.Data.Objects.SqlClient; // needed to convert numbers to strings for linq

比较数字时,请执行以下操作:

1
2
3
4
5
6
7
        // Search Code
            if (!String.IsNullOrEmpty(searchString))
            {
                depts = depts.Where(d => SqlFunctions.StringConvert((double)d.VDN).Contains(searchString.ToUpper())
                || SqlFunctions.StringConvert((double)d.Skill).Contains(searchString.ToUpper()));
            }
        // End Search Code

小精灵。


因为它试图将其转换为SQL,但无法转换。在返回到调用方之前,请取消对ToString的调用,并进行投影。因此,将您的select条款替换为

1
select m.PricingSecurityID

然后说

1
2
3
4
5
return pricingSecurityID
           .AsEnumerable()
           .Select(x => x.ToString())
           .Select(x => new SelectListItem { Text = x, Value = x })
           .ToList();

另外,我注意到您混合了UI关注点和数据查询关注点。这通常是一种不好的做法。实际上,您应该返回ID列表,让代码的UI部分担心是否将其混入正确的表单。


遗憾的是,ef不知道如何转换.toString(),您必须使用嵌入函数sqlFunctions.stringConvert:http://msdn.microsoft.com/en-us/library/dd466292.aspx。int也没有重载,因此您必须将类型转换为double:。-(

1
2
3
4
5
6
var vendors =
   from v in Vendors  
   select new
   {            
       Code = SqlFunctions.StringConvert((double)v.VendorId)
   };

我理解这个问题得到了回答,我同意使用AsEnumerable()是一种方法。不过,我想强调一个常见的场景,我经常遇到这样的场景:AsEnumerable()用于解决此错误的效率很低。

来自.NET语言的关系数据集成查询

The AsEnumerable() operator, unlike ToList() and ToArray(), does not cause execution of the query. It is still deferred. The AsEnumerable() operator merely changes the static typing of the query, turning a IQueryable into an IEnumerable, tricking the compiler into treating the rest of the query as locally executed.

工具书类

  • 我是否误解了linq to sql.aseNumerable()?
  • 了解linq to sql中的.aseNumerable()。
  • 低效方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    IEnumerable<InvoiceDTO> inefficientEnumerable =
         (from a in db.Invoices
         where a.Practice_Key == practiceKey.FirstOrDefault()
         select a
         ).AsEnumerable().
         Select(x => new InvoiceDTO
                                 {
                                     InvoiceID = x.InvoiceID,
                                     PracticeShortName = x.Dim_Practice.Short_Name,
                                     InvoiceDate = x.InvoiceDate,
                                     InvoiceTotal = x.InvoiceAmount,
                                     IsApproved = x.IsApproved,
                                     InvoiceStatus = (
                                                      x.IsApproved == null ?"Pending" :
                                                      x.IsApproved == true ?"Approved" :
                                                      x.IsApproved == false ?"Rejected" :"Unknown"
                                                    ),
                                     InvoicePeriodStartDateText = x.InvoicePeriodStart.ToShortDateString(),
                                     InvoicePeriodEndDateText = x.InvoicePeriodEnd.ToShortDateString(),
                                     InvoicePeriodStartDate = x.InvoicePeriodStart,
                                     InvoicePeriodEndDate = x.InvoicePeriodEnd
                                 }
                                 );

                invoices = inefficientEnumerable.ToList();

    这里,AsEnumerable用于整个表。尽管不需要,但所有列都将被选中。

    更好的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     IQueryable<InvoiceDTO> invoicesQuery =
       (from a in db.Invoices
       where a.Practice_Key == practiceKey.FirstOrDefault()
       select new InvoiceDTO
                {
                 InvoiceID = a.InvoiceID,
                 PracticeShortName = a.Dim_Practice.Short_Name,
                 InvoiceDate = a.InvoiceDate,
                 InvoiceTotal = a.InvoiceAmount,
                 IsApproved = a.IsApproved,
                 InvoiceStatus = (
                                   a.IsApproved == null ?"Pending" :
                                   a.IsApproved == true ?"Approved" :
                                   a.IsApproved == false ?"Rejected" :"Unknown"
                                   ),
                 InvoicePeriodStartDate = a.InvoicePeriodStart,
                 InvoicePeriodEndDate = a.InvoicePeriodEnd
              });


              IEnumerable<InvoiceDTO> betterEnumerable = invoicesQuery.AsEnumerable().
              Select(x => new InvoiceDTO
                                     {
                                         InvoiceID = x.InvoiceID,
                                         PracticeShortName = x.PracticeShortName,
                                         InvoiceDate = x.InvoiceDate,
                                         InvoiceTotal = x.InvoiceTotal,
                                         IsApproved = x.IsApproved,
                                         InvoiceStatus = x.InvoiceStatus,
                                         InvoicePeriodStartDateText = x.InvoicePeriodStartDate.ToShortDateString(),
                                         InvoicePeriodEndDateText = x.InvoicePeriodEndDate.ToShortDateString(),
                                         InvoicePeriodStartDate = x.InvoicePeriodStartDate,
                                         InvoicePeriodEndDate = x.InvoicePeriodEndDate
                                     }
                                     );


    1
    2
    3
    4
    5
    return dbContext.Reporting_DailyNAV_Pricing.AsEnumerable().Select(x => new SelectListItem
    {
        Text = x.PricingSecurityID.ToString(),
        Value = x.PricingSecurityID.ToString()
    }).ToList();