【问题标题】:How to make a generic Func<TEntity, bool>?如何制作通用 Func<TEntity, bool>?
【发布时间】:2017-11-21 10:32:12
【问题描述】:

我正在尝试对我的 Dao 实体框架上下文进行通用查询。像这样:

public List<TEntity> Buscar(Func<TEntity, bool> predicate)
{
    return SelectAll().Where(predicate).AsQueryable().ToList();
}
public List<TEntity> SelectAll()
{
    return DbContexto.Set<TEntity>().ToList();
}

但我找不到如何调用该方法,因为我不知道实体,因此 lambda 表达式不接受我尝试传递的成员。如果我试试这个:

public List<TEnt> Buscar()
{            
    return AutoMapperConfig.Mapper.Map<List<TEntEF>, List<TEnt>>(Dao.Buscar(x => x.ID == 1 ));
}

我在“x.ID”中有一个错误说:“TENtEF”不包含“ID”的定义,并且找不到任何接受“TENtEF”类型的第一个参数的“ID”扩展方法(是是否缺少使用指令或程序集引用?)

如果我这样尝试:

public List<TEnt> Buscar()
{
    Func<PESSOAS, bool> pred = delegate (PESSOAS item)
    {
        return item.ID == 2;
    };

    return AutoMapperConfig.Mapper.Map<List<TEntEF>, List<TEnt>>(Dao.Buscar(pred));
}

我在“(pred)”中没有错误说:无法从“System.Func&lt;EFBcostedSQL.PESSOAS, BOOL&gt;”转换为“System.Func&lt;TEntEF, bool&gt;

我不知道任何其他方法...知道如何解决这个问题吗?

---稍后添加------------------------------------ -------------- 我不想做基类或接口,因为我首先使用 DataBase,如果我必须扩展所有部分类,那没有意义。除此之外,我的基类无法拥有所有类的属性,我希望能够使用任何属性。

现在我明白不可能了,我试试这个,因为我有一个中间层,所以我的视图层看不到我的上下文层。在这个中间层中,我不想为每个实体创建一个类,只有一个通用类,它适用于我的上下文中的所有实体。

【问题讨论】:

  • 您的最后两个代码示例没有意义:您的方法有一个 predicate 参数,但从不使用它。
  • 1) 看起来您正在使用 EF,因此您需要 Expression&lt;Func&lt;TEnt, bool&gt;&gt;,而不仅仅是 func 2) 您可以指定所有 TEnt 将继承自的接口或基类。跨度>
  • 顺便说一句,Buscar 方法称为 SelectAll,它会在查询之前将整个数据库表拖到内存中 - 请不要养成这种习惯。
  • 感谢@Heinzi 的关注。忽略(我在上次编辑中删除)我试图找到如何安装这个谓词。
  • @zaitsman.Yes 你明白了。但我不想这样做,因为我首先使用 DataBase,如果我必须扩展所有部分类,这没有意义。除此之外,我的基类没有办法拥有所有类的属性,我希望能够使用任何属性。

标签: c# .net generics lambda


【解决方案1】:

由于您对特定实体类型 (PESSOAS) 进行过滤,因此您需要返回该特定类型而不是通用 TEnt

public List<PESSOAS> GetPessoasWithID2()
{
    Func<PESSOAS, bool> pred = delegate (PESSOAS item)
    {
        return item.ID == 2;
    };

    return Dao.Buscar(pred);
}

当然可以缩短为

public List<PESSOAS> GetPessoasWithID2()
{
    return Dao.Buscar<PESSOAS>(item => item.ID == 2);
}

【讨论】:

  • 好的。谢谢黑子。那么唯一的解决方案是在 PESSOAS 的特定类中使用?这对我有用,真的谢谢。但是,如果您对在基因类型中使用有任何想法,那将是完美的。
  • @AlamEstudent:“过滤 ID 2”对泛型类型有何意义?
  • 这只是一个例子。它可以是任何东西:ID、NAME、SANITUINE TYPE、MARK 等等。
  • 那么你已经有了它:Dao.Buscar&lt;X&gt;(Y) 是你的通用方法,当你使用它时,你将:X 替换为具体类型,Y 替换为具体过滤器(名称、标记等)。
【解决方案2】:

您的实体必须使用 ID 属性实现通用接口 例如:

public interface IHasId<T> where T: struct
{
        T ID { get; set; }
}

public class PESSOAS: IHasId<int>
{
        [Key]
        public int ID { get; set; }
}

并将其用作:

Func<PESSOAS, bool>

【讨论】:

  • 真的是唯一的解决办法吗?你明白了。但我不想这样做,因为我首先使用的是 DataBase,如果我必须扩展所有部分类来继承接口,这没有任何意义。除此之外,我的基类没有办法拥有所有类的属性,我希望能够使用任何属性
【解决方案3】:

这就是你要找的吗?不是 100% 确定我理解了这个问题。让我知道我是否离题...

class Customer
{
    [Key]
    public string Name { get; set; }
}
class Order
{
    [Key]
    public int OrderNumber { get; set; }
    public decimal Total { get; set; }
}

class MyContext : DbContext
{
    public MyContext()
    {
        //connect MyContext to some data source here

        Customers.Add(new Customer { Name = "John" });
        Customers.Add(new Customer { Name = "Jacob" });
        Customers.Add(new Customer { Name = "Hannah" });
    }
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Order> Orders { get; set; }

    public IQueryable<TEntity> Buscar<TEntity>(Expression<Func<TEntity, bool>> predicate) 
        where TEntity : class
    {
        return this.Set<TEntity>().Where(predicate).AsQueryable<TEntity>();
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyContext _context = new MyContext();
        IQueryable<Customer> _customers = _context.Buscar<Customer>(c=>c.Name.StartsWith("J"));
        foreach(Customer cust in _customers)
        {
            Console.WriteLine("Customer Name=" + cust.Name);
        }
        Console.ReadKey();
    }
}

【讨论】:

  • 是的@ylax,谢谢。我唯一遇到的问题,我很抱歉,因为我知道不可能,我想用通用 T 来调用它,比如 IQueryable _customers = _context.search (c => c.Name.开始于(“J”));。这就是为什么我有一个中间层,这样我的视图层就看不到我的上下文层。在这个中间层中,我不想为每个实体创建一个类,只有一个通用类,它适用于我的上下文中的所有实体。
  • 在某些时候,您必须告诉上下文您要搜索的实体类型。也许有一种方法可以推断出调用代码中的类型?如果是这样,您可以传递一个类型而不是泛型参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-10
  • 2012-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-07
  • 1970-01-01
相关资源
最近更新 更多