构建LINQ的一般查询LINQ

2023-09-05 03:36:52 作者:闭眸

我有两个表的数据库:

 公共类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自己...

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

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

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

解决方案

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

使用这种方法的条件要求防爆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...

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

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.

 
精彩推荐
图片推荐