在 LINQ 表达式中使用方法的解决方法
在我的 ASP.NET MVC3 应用程序中,我有以下使用 EF 实体 的方法:
public IQueryable<Products> GetCreatedProducts(int year)
{
return GetAllProducts().Where(m => Equals(DateUtilities.ExtractYear(m.ProductCreationDate), year));
}
ProductCreationDate
是作为字符串存储在数据库中的字段 >“YYYYMMddhhmm”。
int DateUtilities.ExtractYear(string date)
是我为了从字符串中获取年份而创建的方法。同样,我使用 ExtractMonth
和 ExtractDay
。
但是,当我执行应用程序时,它会启动 NotSupported 异常:
“LINQ to Entities 无法识别“Int32 ExtractYear(System.String)”方法,并且此方法无法转换为存储表达式。”
通过谷歌搜索这个问题,我发现这是 LINQ to Entities 中的一个错误 有人知道解决方法吗?
In my ASP.NET MVC3 application I have the following method that use EF entities:
public IQueryable<Products> GetCreatedProducts(int year)
{
return GetAllProducts().Where(m => Equals(DateUtilities.ExtractYear(m.ProductCreationDate), year));
}
ProductCreationDate
is a field stored in the database as string "YYYYMMddhhmm".
int DateUtilities.ExtractYear(string date)
is a method that I created in order to get the year from the string. Similarly I use ExtractMonth
and ExtractDay
.
However when I execute my application it launches an NotSupported exception:
"LINQ to Entities does not recognize the method 'Int32 ExtractYear(System.String)' method, and this method cannot be translated into a store expression."
By googling the problem I found out that it is a bug in LINQ to Entities Anybody knows a workaround?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我的第一个问题是为什么要将日期作为字符串存储在数据库中?将其存储为日期并通过 Linq 对其进行数据比较。
您遇到的问题是 Linq 在尝试将 Linq 语句编译为原始 SQL 时不理解方法 ExtractYear 是什么
编辑
另一种替代方法是在数据库中创建一个视图,并使用将字符串值表示为日期时间的计算列对该视图进行查询。
My first question would be why are you storing a date in the database as a string? Store it as a date and use data comparison against it through Linq.
The issue that you're coming up against is Linq doesn't understand what the method ExtractYear is when it tries to compile your Linq statement to raw SQL
EDIT
Another alternative would be to create a view in the database and query against the view with a computed column that represents the string value as a datetime.
在这种情况下,您可以采用另一种方式:
不是从字符串中提取年份,而是查找以您要查找的年份开头的所有字符串。
我不确定这些是否适用于月份和日期搜索:
In this case you could go the other way:
Rather than extract the year from the string, find all strings beginning with the year you're after.
I'm not sure if these will work for the Month and Day searches:
我不认为这实际上是一个错误,而是一个限制——没有 SQL 版本的
ExtractYear
,因此不可能执行此查询。您必须重写查询以仅使用 SQL 兼容的命令(如其他一些答案所示)或从数据库中提取大量数据并使用 LINQ-to-Objects 进行过滤(这可能非常昂贵) ,具体取决于您要查询的内容以及匹配的记录数量)。
I don't think this is really a bug so much as a limitation -- there's no SQL version of
ExtractYear
, so it's not possible to execute this query.You'll have to rewrite the query to either use only SQL-compatible commands (like some other answers have shown) or pull lots of data out of the database and do the filtering with LINQ-to-Objects (this could potentially be very expensive, depending on what you're querying and how many of the records match).
您会收到异常,因为您使用
IQueryable
。实体框架将尝试将 where 子句中的谓词转换为 SQL,但 EF 不知道如何转换您的方法。如果您不想(或不能)更改数据库,您仍然有几个选择:
将所有行拉到客户端并在客户端上进行过滤。您可以通过从
IQueryable
更改为IEnumerable
来实现此目的:为了提高效率,您可以使用自己的 SQL(这需要 EF 4.1,并且只能避免将所有产品拉到客户端,而不是服务器上的扫描):
请注意,我很懒,对 SQL 进行了硬编码。您可能应该对其进行参数化,并确保避免任何 SQL 注入攻击。
You get the exception because you work with
IQueryable
. Entity Framework will try to translate the predicate in the where clause into SQL but EF doesn't know how to translate your method.If you don't want to (or can't) change the database you still have a few options:
Pull all rows to the client side and do the filtering on the client. You do this by changing from
IQueryable
toIEnumerable
:To be more efficient you can use your own SQL (this requires EF 4.1 and only avoid pulling all products to the client, not the scan on the server):
Note that I was lazy and hardcoded the SQL. You should probably parametrize it and make sure you avoid any SQL injection attacks.
您可以进行内联提取,如下所示:
You could do the extraction inline, something like this: