【问题标题】:Building Linq generic queries构建 Linq 通用查询
【发布时间】:2014-01-12 17:30:35
【问题描述】:

我有一个包含两个表的数据库:

public class A {
    public string Name { get; set; }
    public int Id { get; set; }
}

public class B {
    public int Id { get; set; }
    public bool Prop1 { get; set; }
    public bool Prop2 { get; set; }
    public bool Prop3 { get; set; }
    public bool Prop4 { get; set; }
}

public class DataContext : DbContext {
    DbSet<A> Table1 { get; set: }
    DbSet<B> Table2 { get; set; }
}

我想编写函数,它将作为参数“Prop1”,“Prop2”,...,“PropX” 并从 Table1 返回适当的行。 像这样的:

public List<A> GetByProp(string prop) {
    var result = new List<A>();

    using (var db = new DataContext()) {
        result = db.Table1.Join(db.Table2, t1=>t1.Id, t2=>t2.Id, (t1,t2)=>new {t1,t2}).
                           Where(????????). //t=>t.t2.prop == true
                           Select(t=>t.t2);

    }
    return result;
}

这样做的正确方法是什么?

我尝试使用表达式树,但我被他们卡住了......

  1. 如何用两个点构建表达式? (t.t2.prop == true)

  2. 如何将匿名类型(由 Join() 生成)传递给泛型

    var p = Expression.Parameter(typeof(???), t2); //??? - anonymous class
    var t = Expression.Constant(true, typeof(bool));
    var e = Expression.Equal(p, t);
    var l = Expression.Lambda<Func<???, bool>>(e, p);
    

【问题讨论】:

  • This 适用于OrderBy,但可以作为起点。
  • 是否需要属性参数为字符串?可以改为表达式吗?

标签: c# .net database linq expression-trees


【解决方案1】:

将条件作为Join 方法源的一部分怎么样?

通过这种方法,您的条件需要Expression&lt;Func&lt;B, true&gt;&gt;,您可以使用表达式树轻松创建一个。

List<T> result;

var param = Expression.Parameter(typeof(B), "x");
var trueExp = Expression.Constant(true);
var condition = Expression.Equal(Expression.Property(param, prop), trueExp);
var whereLambda = Expression.Lambda<Func<B, bool>>(condition, param);

using (var db = new DataContext())
{
    result = db.Table1
               .Join(db.Table2.Where(whereLambda),
                     t1 => t1.Id,
                     t2 => t2.Id,
                     (t1, t2) => new { t1, t2 })
               .Select(t => t.t1)
               .ToList();
}
return result;

更新

如果你想遵循你的初始设计,你应该让编译器推断你的匿名类型:

public static Expression<Func<T, bool>> GetPropertyCondition<T>(T source, string prop)
{
    var param = Expression.Parameter(typeof(T), "x");
    var trueExp = Expression.Constant(true);
    var condition = Expression.Equal(
                        Expression.Property(
                            Expression.Property(param, "t2"), prop),
                            trueExp);
    var whereLambda = Expression.Lambda<Func<T, bool>>(condition, param);
    return whereLambda;
}

你可以这样称呼它:

var result = new List<A>();

var anonymous = new { t1 = (A)null, t2 = (B)null };
var condition = GetPropertyCondition(anonymous, prop);

using (var db = new DataContext())
{
    result = db.Table1.AsQueryable()
               .Join(db.Table2.AsQueryable(), t1 => t1.Id, t2 => t2.Id, (t1, t2) => new { t1, t2 })
               .Where(condition)
               .Select(t => t.t1)
               .ToList();
}
return result;

它使用了这样一个事实,即程序集中具有相同属性集(属性名称和属性类型都必须匹配)的每个匿名类型对象共享相同的底层匿名类。所以这里的typeof(anonymous) 匹配Join 扩展方法返回的类型。

【讨论】:

  • 感谢您的回复。我明天上班试试这个))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多