项目开发知识点汇总:Linq的使用

1、场景:客户数据库为DB2,V8.2,项目启动的时候(大概20年七月份)最新版本的IBM.EntityFrameworkCore还是18年11月底发布的1.3.0.100版本,对应的Microsoft.EmtityFrameworkCore版本是2.0,

  在一个泛型类中可以使用如下的反射来查询数据(_dbSet是Set):

public virtual async Task<T> GetSingleAsync(string id)
{
  return await _dbSet.FirstOrDefaultAsync(p => typeof(T).GetProperty(typeof(T).Name + "Id").GetValue(p).ToString().Equals(id));
}

  但是20年8月后,IBM.EntityFrameworkCore频繁更新,当时升级到的3.1.0.300版本后程序无法运行,当时因为被DB2坑惨了,就没仔细看错误原因就降级了。

  昨天因为Log输出的时候,即使使用了EnableSensitiveDataLogging()仍有部分SQL无法显示参数数据,就尝试升级了下IBM.EntityFrameworkCore,意外发现竟然又更新了,目前的3.1.0.400版本可以正常输入SQL参数了,也不清楚是DB2的原因还是Microsoft.EntityFrameworkCore的原因。

  但是升级版本之后,上面的代码就不能使用了,错误信息如下(隐藏了部分敏感信息):

The LINQ expression 'DbSet<TEntity>
    .Where(o => (PropertyInfo)System.String MaintainNumber.GetValue(o).ToString().Equals(__para_0))' could not be translated. 
Either rewrite the query in a form that can be translated, 
or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). 
See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

  浏览错误信息中的网址:https://go.microsoft.com/fwlink/?linkid=2101038,目测报错原因是无法将反射中的GetValue(p)转换成SQL,因此若想执行改代码必须将数据全部拉到内存中再进行查询,如果数据量大则严重影响性能,因此新版本的EFCore禁止了此类调用(大概是EFCore3.0版本之后)。

  正确的处理方式应该是传一个表达式树进去,调用查询方法之前就写好Where语句:

var result = await GetSingleAsync(x => x.Id.Equals(id));

...
public virtual async Task<T> GetSingleAsync(Expression<Func<T, bool>>)
{
  return await _dbSet.FirstOrDefaultAsync(p => typeof(T).GetProperty(typeof(T).Name + "Id").GetValue(p).ToString().Equals(id));
}

  

  

posted @ 2021-02-08 10:50  左崔吉  阅读(360)  评论(0)    收藏  举报