构建LINQ的一般查询 [英] Building Linq generic queries

查看:147
本文介绍了构建LINQ的一般查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个表的数据库:

 公共类A {
    公共字符串名称{;组; }
    公众诠释编号{获得;组; }
}

公共类B {
    公众诠释编号{获得;组; }
    公共BOOL为prop1 {获得;组; }
    公共BOOL Prop2 {获得;组; }
    公共BOOL Prop3 {获得;组; }
    公共BOOL Prop4 {获得;组; }
}

公共类的DataContext:{的DbContext
    DbSet< A>表1 {获得;组: }
    DbSet< B>表2 {获得;组; }
}
 

我想写的功能,这将作为参数为prop1,Prop2,......,PropX 从表1返回相应的行。 事情是这样的:

 公开名单< A> GetByProp(字符串道具){
    VAR的结果=新名单,其中,A>();

    使用(VAR DB =新的DataContext()){
        结果= db.Table1.Join(db.Table2中,t1 => t1.Id,T2 => t2.Id,(T1,T2)=>新建{T1,T2})。
                           哪里(????????)。 //t=>t.t2.prop ==真
                           选择(T => t.t2);

    }
    返回结果;
}
 

什么是正确的方式做到这一点?

我试图用防爆pression树,但我得到stucked自己...

  1. 如何建立前pression有两个点? (t.t2.prop ==真)

  2. 如何我可以通过匿名类型(join()方法生成),以通用

      VAR P =前pression.Parameter(typeof运算(???),T2); // ??? - 匿名类
    VAR T =前pression.Constant(真正的typeof(布尔));
    变种E =前pression.Equal(P,T);
    变种L =前pression.Lambda< Func键< ???,布尔>>(E,P);
     

解决方案

如何放置状态的一个环节加入法源?

使用这种方法的条件要求防爆pression< Func键< B,真>> 键,您可以用防爆pression树很容易地之一。

 名单,其中,T>结果;

VAR参数=前pression.Parameter(typeof运算(B),X);
VAR trueExp =前pression.Constant(真正的);
VAR条件=前pression.Equal(出pression.Property(参数,道具),trueExp);
VAR whereLambda =前pression.Lambda< Func键< B,布尔>>(条件参数);

使用(VAR DB =新的DataContext())
{
    结果= db.Table1
               。加入(db.Table2.Where(whereLambda)
                     T1 => t1.Id,
                     T2 => t2.Id,
                     (T1,T2)=>新{T1,T2})
               。选择(T => t.t1)
               .ToList();
}
返回结果;
 

更新

如果你想跟随你的初始设计应该使编译器推断出你的匿名类型:

 公共静态防爆pression< Func键< T,布尔>> GetPropertyCondition< T>(T源,串道具)
{
    变种参数=实施例pression.Parameter(typeof运算(T),×);
    VAR trueExp =前pression.Constant(真正的);
    VAR条件=前pression.Equal(
                        防爆pression.Property(
                            防爆pression.Property(参数,T2),丙)
                            trueExp);
    VAR whereLambda =前pression.Lambda< Func键< T,布尔>>(条件参数);
    返回whereLambda;
}
 

,你可以这样调用它的:

  VAR的结果=新名单,其中,A>();

VAR匿名=新{T1 =(A)空,T2 =(B)空};
VAR条件= GetPropertyCondition(匿名,道具);

使用(VAR DB =新的DataContext())
{
    结果= db.Table1.AsQueryable()
               。加入(db.Table2.AsQueryable()中,t1 => t1.Id,T2 => t2.Id,(T1,T2)=>新建{T1,T2})
               。凡(条件)
               。选择(T => t.t1)
               .ToList();
}
返回结果;
 

它使用的事实,具有相同的属性集(包括属性名称和属性类型必须匹配)大会占有率在同一个底层匿名类的每一个匿名类型的对象。因此,的typeof(匿名)此不匹配的类型由返回加入扩展方法。

I have a database with two tables:

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; }
}

I want to write function, which will take as parameter "Prop1", "Prop2", ... , "PropX" and return appropriate rows from Table1. Something like this:

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;
}

What is a proper way to do this?

I've tried to use Expression Tree, but I got stucked their...

  1. How to build expression with two dots? (t.t2.prop == true)

  2. How can I pass anonymous type (which Join() generates) to generic

    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);
    

解决方案

How about placing the condition as a part of Join method source?

With that approach your condition requires Expression<Func<B, true>> and you can easily make one using Expression Tree.

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;

Update

If you want to follow your initial design you should make the compiler infer your anonymous type:

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;
}

and you can call it like that:

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;

it uses the fact, that every anonymous type object with the same set of properties (both property name and property type have to match) within the assembly share the same underlying anonymous class. So typeof(anonymous) here matches type returned by Join extension method.

这篇关于构建LINQ的一般查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆