使用链接实体中的特定字段构建 lambda 表达式树
Build an lambda Expression tree with a specific field in a linked entity
数据模型
public class TABLE
{
[Key]
public int ID { get; set; }
public int ONEFIELD { get; set; }
// -------------------- ForeignKey --------------------
[ForeignKey("People")]
public long PeopleID { get; set; }
public virtual People People { get; set; }
}
public class People
{
[Key]
public long PeopleID { get; set; }
public int CountryID { get; set; }
}
我需要构建一个 lambda 来查询这个模型:
Get TABLE.ONEFIELD = 1 AND TABLE.PEOPLE.COUNTRYID = 6
等效于 LINQ
_context.TABLEs
.Where(e => e.ONEFIELD == 1)
.Include(e => e.People)
.Where(i=>i.People.CountryID == 6);
我的尝试
public static Expression<Func<TEntity, bool>> BuildLambda<TEntity>(OBJTYPE obj)
{
var item = Expression.Parameter(typeof(TEntity), "table");
Expression query = null;
// 1
var prop1 = Expression.Property(item, "ONEFIELD");
var value1 = Expression.Constant(1);
var equal1 = Expression.Equal(prop1, value1);
var lambdaFIELDONE = Expression.Lambda<Func<TEntity, bool>>(equal1, item);
query = lambdaFIELDONE.Body;
// 2
var prop2 = Expression.Property(item, typeof(People).Name + ".CountryID");
var value2 = Expression.Constant(6);
var equal2 = Expression.Equal(prop2, value2);
var lambdaCOUNTRYID = Expression.Lambda<Func<TEntity, bool>>(equal2, item);
query = Expression.And(query, lambdaCOUNTRYID);
}
但我收到此错误
System.ArgumentException: Instance property 'People.CountryID' is not defined for type 'SOLUTION.Models.TABLE'
我不需要泛型,只需要一个固定的 lambda(而且我不能使用 LINQ)。
我尝试了几种方法来捕捉 People.CountryID 喜欢
Expression.Property(item1, typeof(People).GetProperty("CountryID"));
Expression.Property(item, typeof(People).Name+"." + typeof(People).GetProperty("CountryID"));
Expression.Property(item, typeof(People).Name + "." + typeof(People).GetProperties().Where(x => x.Name == "CountryID").FirstOrDefault().Name);
没有成功
有什么想法吗?谢谢
因此,要构建嵌套的 属性 访问,您必须嵌套访问每个级别的 Expression
。然后你可以将测试组合成一个主体,最后为结果创建 lambda:
public static Expression<Func<TEntity, bool>> BuildLambda<TEntity>(OBJTYPE obj) {
// (TEntity table)
var parmTable = Expression.Parameter(typeof(TEntity), "table");
// table.ONEFIELD
var prop1 = Expression.Property(parmTable, "ONEFIELD");
// table.ONEFIELD == 1
var equal1 = Expression.Equal(prop1, Expression.Constant(1));
// table.People
var prop2_1 = Expression.Property(parmTable, nameof(People));
// table.People.CountryID
var prop2_2 = Expression.Property(prop2_1, "CountryID");
// table.People.CountryID == 6
var equal2 = Expression.Equal(prop2_2, Expression.Constant(6));
// table.ONEFIELD == 1 && table.People.CountryID == 6
var finalBody = Expression.AndAlso(equal1, equal2);
// table => table.ONEFIELD == 1 && table.People.CountryID == 6
return Expression.Lambda<Func<TEntity, bool>>(finalBody, parmTable);
}
使用 LINQPad,您可以创建一个示例 lambda,然后使用 Dump
方法,您会看到创建了一个嵌套的 FieldExpression
,这就是您调用 [=15] 时创建的内容=]:
Expression<Func<TEntity, int>> f = t => t.People.CountryID;
f.Dump();
数据模型
public class TABLE
{
[Key]
public int ID { get; set; }
public int ONEFIELD { get; set; }
// -------------------- ForeignKey --------------------
[ForeignKey("People")]
public long PeopleID { get; set; }
public virtual People People { get; set; }
}
public class People
{
[Key]
public long PeopleID { get; set; }
public int CountryID { get; set; }
}
我需要构建一个 lambda 来查询这个模型:
Get TABLE.ONEFIELD = 1 AND TABLE.PEOPLE.COUNTRYID = 6
等效于 LINQ
_context.TABLEs
.Where(e => e.ONEFIELD == 1)
.Include(e => e.People)
.Where(i=>i.People.CountryID == 6);
我的尝试
public static Expression<Func<TEntity, bool>> BuildLambda<TEntity>(OBJTYPE obj)
{
var item = Expression.Parameter(typeof(TEntity), "table");
Expression query = null;
// 1
var prop1 = Expression.Property(item, "ONEFIELD");
var value1 = Expression.Constant(1);
var equal1 = Expression.Equal(prop1, value1);
var lambdaFIELDONE = Expression.Lambda<Func<TEntity, bool>>(equal1, item);
query = lambdaFIELDONE.Body;
// 2
var prop2 = Expression.Property(item, typeof(People).Name + ".CountryID");
var value2 = Expression.Constant(6);
var equal2 = Expression.Equal(prop2, value2);
var lambdaCOUNTRYID = Expression.Lambda<Func<TEntity, bool>>(equal2, item);
query = Expression.And(query, lambdaCOUNTRYID);
}
但我收到此错误
System.ArgumentException: Instance property 'People.CountryID' is not defined for type 'SOLUTION.Models.TABLE'
我不需要泛型,只需要一个固定的 lambda(而且我不能使用 LINQ)。
我尝试了几种方法来捕捉 People.CountryID 喜欢
Expression.Property(item1, typeof(People).GetProperty("CountryID"));
Expression.Property(item, typeof(People).Name+"." + typeof(People).GetProperty("CountryID"));
Expression.Property(item, typeof(People).Name + "." + typeof(People).GetProperties().Where(x => x.Name == "CountryID").FirstOrDefault().Name);
没有成功
有什么想法吗?谢谢
因此,要构建嵌套的 属性 访问,您必须嵌套访问每个级别的 Expression
。然后你可以将测试组合成一个主体,最后为结果创建 lambda:
public static Expression<Func<TEntity, bool>> BuildLambda<TEntity>(OBJTYPE obj) {
// (TEntity table)
var parmTable = Expression.Parameter(typeof(TEntity), "table");
// table.ONEFIELD
var prop1 = Expression.Property(parmTable, "ONEFIELD");
// table.ONEFIELD == 1
var equal1 = Expression.Equal(prop1, Expression.Constant(1));
// table.People
var prop2_1 = Expression.Property(parmTable, nameof(People));
// table.People.CountryID
var prop2_2 = Expression.Property(prop2_1, "CountryID");
// table.People.CountryID == 6
var equal2 = Expression.Equal(prop2_2, Expression.Constant(6));
// table.ONEFIELD == 1 && table.People.CountryID == 6
var finalBody = Expression.AndAlso(equal1, equal2);
// table => table.ONEFIELD == 1 && table.People.CountryID == 6
return Expression.Lambda<Func<TEntity, bool>>(finalBody, parmTable);
}
使用 LINQPad,您可以创建一个示例 lambda,然后使用 Dump
方法,您会看到创建了一个嵌套的 FieldExpression
,这就是您调用 [=15] 时创建的内容=]:
Expression<Func<TEntity, int>> f = t => t.People.CountryID;
f.Dump();