【C#】LINQ to Entities 不识别方法“System.String ToXX()”,因此该方法无法转换为存储表达式

使用LINQ to Entities一不小心就会碰上类似的错误:
LINQ to Entities 不识别方法“XX”,因此该方法无法转换为存储表达式,这是因为LINQ语句最后都是要转为sql语句来执行的,当它转换后,发现sql语句中要执行的方法“XX”,并不是一个在数据库中的存储过程函数,也无法进行转换为存储表达式。

主要分为三种情况,下面用各自的解决方式区别应对:

一.作为判断的局部变量在linq语句中调用了函数:

string date = "2018-10-01 00:00:00";
var query = from item in context.Goods
            where item.SaleTime == DateTime.Parse(date)
            select item;

这种处理方式最为简单,也就是保证linq语句中尽量不用系统语言的函数,所以上面直接将date设置为DateTime就可以了,保证都是数据库的时间类型。

DateTime date = DateTime.Parse("2018-10-01 00:00:00");
var query = from item in context.Goods
            where item.SaleTime == date
            select item;

二.要得到数据处理结果而不得不调用方法:

var query = from item in context.Goods
            group item by item.Created.ToString() into g
            select new { SaleTime = g.Key.ToString(), Count = g.Count() };

这里排序和查询结果中都用到了ToString方法,外部需要的SaleTime是一个字符串类型而不是时间类型。多说一句,有的可能会说这里直接用时间类型,等到外部需要时再ToString()转为字符串。实际是考虑到字符串可为空,那样的话使用ToString时就会出错。
这个时候解决思路始终一条就是,先在内存中使用LINQ to Objects,然后对数据集进行第二次处理。当数据集在内存中时,调用系统的函数处理数据就很合理了。只是数据量大的时候,对内存和处理速度是一个考验。

var query = from item in context.Goods.ToList()
            group item by item.Created.ToString() into g
            select new { SaleTime = g.Key.ToString(), Count = g.Count() };

三.转变为使用数据库能支持的调用方法:

var query = from item in context.Goods.ToList()
            select new { SaleTime = g.Key.ToString(), Count = g.Count() };

这里,跟上面的实例代码类似,我们是在处理时间字段时,有些数据库是有自己的时间处理函数的,C#在系统层通过使用SqlFunctions,是可以做一个桥接转换的,实际还是调用的数据库内置函数。所以解决方式如下:

var query = from item in context.Goods.ToList()
            select new { SaleTime = SqlFunctions.DateName("year", g.Key) + "-" 
                + SqlFunctions.DateName("month", g.Key) +"-"
                + SqlFunctions.DateName("day",g.Key), Count = g.Count() };

 

总结,三种情况,遇到最多且使用最多的应该是第二种情况,第一种基本可忽略,第三种不具有通用性。所以,最好的处理方式就是Linq-to-entities 转换到Linq-to-objects,然后在内存中调用函数进行二次处理

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值