如何将 Expression<T, bool> where TO : Custom Class 存储到 Expression<CustomClass, bool> 属性 中?
How can I store an Expression<T, bool> where T : CustomClass into an Expression<CustomClass, bool> property?
此问题与 的上下文相同。我正在复制粘贴说明部分,因为它与两者都相关:
我们有一个项目使用遗留数据库,EntityFramework 无法使用。
所以我们已经开始构建一个穷人 EntityFramework,其基础 class CustomBaseTable
实体 class 是从中派生出来的。另一个 class、CustomQueryBuilder
具有构建 SQL 查询的方法:BuildSelectQuery(CustomBaseTable p_objEntity)
等等。
我们的第一个版本可以很好地构建查询,但是我们使用的是相当粗糙的对象,这些对象并不是很灵活(为了保存细节而保留 space)。
我最近意识到使用 Expression
个对象会更加高效和灵活。
所以我想向 CustomBaseTable
添加一个方法,它的工作方式或多或少类似于 Where()
:
EntityTable z_objEntity = new EntityTable();
z_objEntity.CustomWhere(t => t.Field1 == Value1);
CustomQueryBuilder z_objBuilder = new CustomQueryBuilder(DBTypeEnum.DataBaseType);
string z_strQuery = z_objBuilder.BuildSelectQuery(z_objEntity);
结束说明。
我希望 CustomWhere()
将该表达式存储在 属性 中,并在 BuildSelectQuery(CustomBaseTable p_objEntity)
中使用后者以将其解析为敏锐的 SQL Where 子句。 (当然,它会在 Update
和 Delete
查询也会使用的单独方法中发生。)
我在CustomBaseTable
中写了一个属性:
public Expression<Func<CustomBaseTable, bool>> WhereClauseExpression
所以CustomWhere()
应该做类似
的事情
public static void CustomWhere<T>(this T z_objTable, Expression<Func<T, bool>> p_expWhereClause) where T : CustomBaseTable
{
z_objTable.WhereClauseExpression = p_expWhereClause;
}
但是,作为 Expression<Func<T, bool>>
对象的 p_expWhereClause
无法转换为 Expression<Func<CustomBaseTable, bool>>
。
我尝试创建一个 ICustomBaseTable
,CustomBaseTable
从中派生并使 WhereClauseExpression
成为 Expression<Func<ICustomBaseTable, bool>>
,结果相同。
受到this question的启发,我尝试了
z_objTable.WhereClauseExpression = LambdaExpression.Lambda<Func<CustomBaseTable, bool>>(p_expWhereClause.Body, p_expWhereClause.Parameters);
同样,转换失败。
我认为如果不在 CustomBaseTable<T>
中声明 T
,我无法将 WhereClauseExpression
设为 Expression<Func<T, bool>>
,我也不想要。
当然,解决方法是在CustomQueryBuilder
中有一个方法,将表达式解析为Where子句,然后将后者存储在WhereClause
String
属性,但我宁愿一次生成所有 SQL 代码;它让我觉得更干净。
有没有办法将 Expression
存储到 属性 中,这对任何派生的 class 都有效?
最后,答案是:我做不到……不过没关系。
如题中所说,我试过了
public static void CustomWhere<T>(this T z_objTable, Expression<Func<T, bool>> p_expWhereClause) where T : CustomBaseTable
{
z_objTable.WhereClauseExpression = LambdaExpression.Lambda<Func<CustomBaseTable, bool>>(p_expWhereClause.Body, p_expWhereClause.Parameters);
}
还是不行,因为Parameters
中的参数类型是T
,而不是CustomBaseTable
。
所以经过一些摆弄后,CustomWhere()
现在看起来像
public static void CustomWhere<T>(this T z_objTable, Expression<Func<T, bool>> p_expWhereClause) where T : CustomBaseTable
{
z_objTable.WhereClauseExpression = Expression.Lambda<Func<CustomBaseTable, bool>>(p_expWhereClause.Body, p_expWhereClause.Parameters.Select(p => Expression.Parameter(typeof(CustomBaseTable), p.Name)));
}
不仅转换工作完美,而且更好的是,z_objTable.WhereClauseExpression
中的 Expression
个对象,从 Body
开始,使用 T
个对象而不是 CustomBaseTable
。我需要的是子表达式使用 T
,这就是我最后得到的。
此问题与
我们有一个项目使用遗留数据库,EntityFramework 无法使用。
所以我们已经开始构建一个穷人 EntityFramework,其基础 class CustomBaseTable
实体 class 是从中派生出来的。另一个 class、CustomQueryBuilder
具有构建 SQL 查询的方法:BuildSelectQuery(CustomBaseTable p_objEntity)
等等。
我们的第一个版本可以很好地构建查询,但是我们使用的是相当粗糙的对象,这些对象并不是很灵活(为了保存细节而保留 space)。
我最近意识到使用 Expression
个对象会更加高效和灵活。
所以我想向 CustomBaseTable
添加一个方法,它的工作方式或多或少类似于 Where()
:
EntityTable z_objEntity = new EntityTable();
z_objEntity.CustomWhere(t => t.Field1 == Value1);
CustomQueryBuilder z_objBuilder = new CustomQueryBuilder(DBTypeEnum.DataBaseType);
string z_strQuery = z_objBuilder.BuildSelectQuery(z_objEntity);
结束说明。
我希望 CustomWhere()
将该表达式存储在 属性 中,并在 BuildSelectQuery(CustomBaseTable p_objEntity)
中使用后者以将其解析为敏锐的 SQL Where 子句。 (当然,它会在 Update
和 Delete
查询也会使用的单独方法中发生。)
我在CustomBaseTable
中写了一个属性:
public Expression<Func<CustomBaseTable, bool>> WhereClauseExpression
所以CustomWhere()
应该做类似
public static void CustomWhere<T>(this T z_objTable, Expression<Func<T, bool>> p_expWhereClause) where T : CustomBaseTable
{
z_objTable.WhereClauseExpression = p_expWhereClause;
}
但是,作为 Expression<Func<T, bool>>
对象的 p_expWhereClause
无法转换为 Expression<Func<CustomBaseTable, bool>>
。
我尝试创建一个 ICustomBaseTable
,CustomBaseTable
从中派生并使 WhereClauseExpression
成为 Expression<Func<ICustomBaseTable, bool>>
,结果相同。
受到this question的启发,我尝试了
z_objTable.WhereClauseExpression = LambdaExpression.Lambda<Func<CustomBaseTable, bool>>(p_expWhereClause.Body, p_expWhereClause.Parameters);
同样,转换失败。
我认为如果不在 CustomBaseTable<T>
中声明 T
,我无法将 WhereClauseExpression
设为 Expression<Func<T, bool>>
,我也不想要。
当然,解决方法是在CustomQueryBuilder
中有一个方法,将表达式解析为Where子句,然后将后者存储在WhereClause
String
属性,但我宁愿一次生成所有 SQL 代码;它让我觉得更干净。
有没有办法将 Expression
存储到 属性 中,这对任何派生的 class 都有效?
最后,答案是:我做不到……不过没关系。
如题中所说,我试过了
public static void CustomWhere<T>(this T z_objTable, Expression<Func<T, bool>> p_expWhereClause) where T : CustomBaseTable
{
z_objTable.WhereClauseExpression = LambdaExpression.Lambda<Func<CustomBaseTable, bool>>(p_expWhereClause.Body, p_expWhereClause.Parameters);
}
还是不行,因为Parameters
中的参数类型是T
,而不是CustomBaseTable
。
所以经过一些摆弄后,CustomWhere()
现在看起来像
public static void CustomWhere<T>(this T z_objTable, Expression<Func<T, bool>> p_expWhereClause) where T : CustomBaseTable
{
z_objTable.WhereClauseExpression = Expression.Lambda<Func<CustomBaseTable, bool>>(p_expWhereClause.Body, p_expWhereClause.Parameters.Select(p => Expression.Parameter(typeof(CustomBaseTable), p.Name)));
}
不仅转换工作完美,而且更好的是,z_objTable.WhereClauseExpression
中的 Expression
个对象,从 Body
开始,使用 T
个对象而不是 CustomBaseTable
。我需要的是子表达式使用 T
,这就是我最后得到的。