为什么LINQ to Entities无法识别方法’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获取值时:
public class DataRepository { public mydataEntities1 dbContext = new mydataEntities1(); public List 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。 我想,从理论上讲,它可以,但没有实施。
您只需在获得结果后执行投影:
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 Entities中没有包含翻译,因为它没有意义。 将您的select子句更改为:
select new SelectListItem { Text = m.PricingSecurityID, Value = m.PricingSecurityID }
如果您确实需要执行LINQ to Entities不支持的操作,请使用AsEnumerable
从数据库查询转换为进程内:
public List 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(); }
顺便说一句,我同意Jason的反对意见。 你最好还是返回一个在别处呈现的List
。
另请注意,如果您只是要使用单个select
子句或只使用where
子句,查询表达式实际上不会增加太多 – 调用LINQ扩展方法最终可能会减少混乱,特别是如果您想调用哪些方法查询表达式(例如ToList
) 不支持。
因为它试图将其转换为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部分担心将其分成正确的forms。
这个怎么样。 在此示例中,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。
遗憾的是EF不知道如何转换.ToString()你必须使用嵌入式函数SqlFunctions.StringConvert: http : //msdn.microsoft.com/en-us/library/dd466292.aspx此外,int也没有重载所以你必须typecast加倍:-(
var vendors = from v in Vendors select new { Code = SqlFunctions.StringConvert((double)v.VendorId) };
我知道这个问题已得到解答,我同意使用AsEnumerable()
是AsEnumerable()
的方法。 但是,我想强调一个常见的情况,我经常遇到AsEnumerable()
无效率地解决此错误。
来自.NET语言 – 关系数据的集成查询
与ToList()和ToArray()不同,AsEnumerable()运算符不会导致执行查询。 它仍然推迟。 AsEnumerable()运算符只是更改查询的静态类型,将IQueryable转换为IEnumerable,欺骗编译器将查询的其余部分视为本地执行。
参考
- 我误解了LINQ to SQL .AsEnumerable()?
- 在LINQ to SQL中理解.AsEnumerable()
效率低下的方式
IEnumerable 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 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 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 } );
return dbContext.Reporting_DailyNAV_Pricing.AsEnumerable().Select(x => new SelectListItem { Text = x.PricingSecurityID.ToString(), Value = x.PricingSecurityID.ToString() }).ToList();