为什么LINQ to Entities无法识别方法'System.String ToString()?

时间:2012-04-11 16:42:06

标签: asp.net-mvc linq entity-framework

在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获取值时:

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();
        }
    }

8 个答案:

答案 0 :(得分:54)

无法转换为SQL。我想,从理论上讲,它可以,但尚未实施。

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

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

答案 1 :(得分:17)

如果它已经是一个字符串,你为什么要首先打电话给ToString?我怀疑LINQ to Entities中没有包含翻译,因为它没有意义。将您的select子句更改为:

select new SelectListItem
{
    Text = m.PricingSecurityID,
    Value = m.PricingSecurityID
}

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

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<string>

另请注意,如果您只是将使用单个select子句或仅使用where子句,则查询表达式实际上不会增加​​太多 - 调用LINQ扩展方法最终可以减少混乱,特别是如果要调用查询表达式中支持的方法(例如ToList)。

答案 2 :(得分:4)

因为它试图将其转换为SQL,所以它不能。取消对ToString的呼叫,并在返回呼叫者之前进行预测。因此,请用

替换select子句
select m.PricingSecurityID

然后说

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

此外,我注意到您正在混合UI问题和数据查询问题。这通常是一种不好的做法。实际上,您应该返回ID列表,让代码的UI部分担心将其分成正确的形式。

答案 3 :(得分:4)

这个怎么样?在此示例中,db中的VDN字段和Skill字段都是整数。我正在寻找两个领域的比赛,所以我有两个比较。

包括这个:

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

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

        // 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

Workie。

答案 4 :(得分:3)

可悲的是,EF不知道如何转换.ToString()你必须使用嵌入式函数SqlFunctions.StringConvert:http://msdn.microsoft.com/en-us/library/dd466292.aspx同样没有int的重载所以你必须强制转换为double: - (

var vendors = 
   from v in Vendors  
   select new
   {             
       Code = SqlFunctions.StringConvert((double)v.VendorId)
   }; 

答案 5 :(得分:1)

我知道这个问题已得到解答,我同意使用AsEnumerable()是可行的方法。但是,我想强调一个常见的情况,即我经常遇到使用AsEnumerable()效率低下来解决此错误的问题。

来自.NET Language-Integrated Query for Relational Data

  

与ToList()和ToArray()不同,AsEnumerable()运算符不会导致执行查询。它仍然是推迟的。 AsEnumerable()运算符只是更改查询的静态类型,将IQueryable转换为IEnumerable,欺骗编译器将查询的其余部分视为本地执行。

<强>参考

  1. Am I misunderstanding LINQ to SQL .AsEnumerable()?
  2. Understanding .AsEnumerable() in LINQ to SQL
  3. 效率低下

    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用于整个表格。尽管不需要,但所有列都会被选中。

    更好的方式

     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
                                     }
                                     );
    

答案 6 :(得分:0)

尝试使用VB.NET进行此操作,重要点是您需要获得答案中所述的AsEnumerable结果。

Dim _EventsDaysResult = From ED In TAdbContext.EventPolicies.AsEnumerable
                                    Where ED.EventID = EID
                                    Select New With {ED.EventID, 
                                    .DayInfo = 
                                    ED.EventDay.GetValueOrDefault.ToShortDateString & " ( " & ED.EventDayTitle & " ) "}

答案 7 :(得分:-3)

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