微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将 Expression<Func<T, bool>> 转换为另一个谓词表达式 Expression<Func<U, bool>>

如何解决将 Expression<Func<T, bool>> 转换为另一个谓词表达式 Expression<Func<U, bool>>

我想将一个谓词表达式(Expression>)转换为另一个谓词表达式(Expression>)但转换后我无法通过 LINQ 进行查询。 我已经尝试 thisthis 方法,但没有任何工作正常 谁能告诉我如何正确地做到这一点,我解决这个问题的方法

using System;
using System.Linq;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Reflection;

public class ItemEntity {
    public int ItemId {set;get;}
    public int ItemParentId {set;get;}
    public int ItemName {set;get;}
}

public class Item {
   public int Id{ set;get;}
   public int ParentId{set;get;}
   public int Name {set;get;}
}

public class Program
{
    
    public static Item Convert(ItemEntity itemChild)
    {
        return new Item()
        {
            Id = itemChild.ItemId,ParentId = itemChild.ItemParentId,Name = itemChild.ItemName
        };
    }
    
    public async Task<IList<ItemEntity>> SelectAsync(Expression<Func<ItemEntity,bool>> predicate)
    {
        // using Microsoft.EntityFrameworkCore;
        // private readonly DbContext _context; // Injected globally by using Service.AddScoped<ItemContext>();
        // return await _context.Set<ItemEntity>().AsNoTracking().Where(predicate).ToListAsync();
        return await Task.Run(() => new List<ItemEntity>()); // actually return the result with matching predicate
    }
    public async Task<List<Item>> GetItems(Expression<Func<Item,bool>> expression)
    {
        
            MethodInfo convertMethod = ((Func<ItemEntity,Item>)Convert).Method;
            
            var p = Expression.Parameter(typeof(ItemEntity));
            var converted = Expression.Lambda<Func<ItemEntity,bool>>(
                Expression.Invoke(expression,Expression.Convert(p,typeof(Item),convertMethod)),p);
            
            IList<ItemEntity> res = await SelectAsync(converted);
            var t = res.Select(x => Convert(x)).ToList();
            return t;
    }
    
    public static void Main()
    {
        Program pr = new Program();
        Func<Expression<Func<Item,bool>>,Task<List<Item>>> getItem = pr.GetItems;
        var res = getItem.Invoke(x => x.Id.Equals(1));
        Console.WriteLine("Hello World");
    }
}

但我收到错误

无法翻译 LINQ 表达式 'DbSet()\r\n .Where(i => ((Item)i).Id.Equals(__Id_0))'。以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用,显式切换到客户端评估。有关详细信息,请参阅 https://go.microsoft.com/fwlink/?linkid=2101038

我无法正确理解它,根据我的理解,我使用 ToList() 进行客户端评估,但还提供了将 ItemEntity 转换为 Item 的方法

我还有其他方法可以基于 ItemEntity 创建新的表达式树,然后在 DBSet 上查询吗? 任何帮助表示赞赏

使用的版本:

  • 点网 5.0
  • Microsoft.EntityFrameworkCore 5.0.6
  • 实体框架 6.4.4
  • 数据库 sql Server

解决方法

尝试以下方法。主要思想是在具体化之前在预计的 DTO 上准确使用过滤器。

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;

public class ItemEntity
{
    public int ItemId { set; get; }
    public int ItemParentId { set; get; }
    public int ItemName { set; get; }
}

public class Item
{
    public int Id { set; get; }
    public int ParentId { set; get; }
    public int Name { set; get; }
}

public class Program
{
    public static Expression<Func<ItemEntity,Item>> ToItem()
    {
        return itemChild => new Item
        {
            Id = itemChild.ItemId,ParentId = itemChild.ItemParentId,Name = itemChild.ItemName
        };
    }

    public Task<IList<Item>> SelectAsync(Expression<Func<Item,bool>> predicate)
    {
        return _context.Set<ItemEntity>()
            .AsNoTracking()
            .Select(ToItem())
            .Where(predicate)
            .ToListAsync();

        //return Task.Run(() => new List<ItemEntity>().AsQueryable().Select(ToItem()).Where(predicate).ToList());
    }

    public async Task<IList<Item>> GetItems(Expression<Func<Item,bool>> expression)
    {
        var res = await SelectAsync(expression);
        return res;
    }

    public static void Main()
    {
        var pr = new Program();
        var res = pr.GetItems(x => x.Id == 1);
        Console.WriteLine("Hello World");
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。