创建一个通用表达式来查询EntityFramework

时间:2018-01-15 22:17:12

标签: c# entity-framework linq linqkit

我有很多实体是由EF针对现有数据库生成的。这些实体中的大多数都具有“名称”属性。我想要一个方法,它接受泛型类型的表达式,并传入一个字符串值,最终将与底层实体的name属性进行比较。

到目前为止,我有这样的事情:

T SpecialLookup(DbSet<T> dbSet, Func<T, string, bool> exp, string specialParam) 
where T: class, new() {
  //here we can do something with specialParam first like clean it up.
  //now pass in the specialParam to the underlying query which can 
  //ultimately look up a matching object by "name == specialParam".
  var predicate = PredicateBuilder.New<T>(x => exp(x, specialParam));
  var obj = dbSet.AsExpandable().SingleOrDefault(predicate);
  return obj;
}

这里的想法是,我可以调用查找函数并传入一个特殊值,并使用特殊值作为参数在DbSet上调用委托。

SpecialLookup(dbContext.SomeEntities, 
 delegate(SomeEntity obj, string name) { 
  return obj.name == name;
 }, 
 " special"
);

我在这里使用LinkqKit尝试使这项工作,但我收到错误“无法将FieldExpression转换为LambdaExpression”。

我的第一个问题是:是否有更好/更简单的方法来实现这一目标?我这太复杂了吗?我甚至需要使用LinqKit吗?

第二:我怎样才能克服这个错误?

1 个答案:

答案 0 :(得分:0)

这几乎就像你使用linq重写linq扩展。如上所述,如果您已经写出了X和Y场景以及您希望实现的目标,那将会很有帮助。我个人知道,当我想要这样的东西时,我已经使用了表达式:

private List<TEntity> GetEntities<TEntity>(Expression<Func<TEntity, bool>> 
predicate = null) where TEntity : class
{
    using (var context = new ExpensesEntities())
    {
        IQueryable<TEntity> data = context.Set<TEntity>();
        if (predicate != null)
        {
            data = data.Where(predicate);
        }

        return data.ToList();
     }
 }

当我有一个存储库模式时,我使用了这个,我有两个不同的表(在实例中更多)。我想把上下文部分包装起来为我自动调用dispose(using(var context = new Context()))并且只处理问题的内容。这本质上是哪个表以及我想要运行谓词的属性。因此,在下面的示例中,我将如何为所有表调用此函数,然后为另一个表在TypeId的属性上为其添加谓词。

public List<X> GetCategories() => GetEntities<X>();
public List<Y> GetTypes() => GetEntities<Y>(x => x.TypeID != 3);