我正在使用 EntityFramework 和LinqKit来构建被翻译成 SQL 的表达式树。我们还使用规范模式来组织我们的查询。
几乎我们所有的领域对象都需要通过描述来执行查询,但在其中一些类中,属性称为“名称”,在其他类中称为“描述”等。
所以最初定义了一个接口如下:
public interface IDescritible
{
string Description { get; }
}
当我尝试使用它在类中显式实现并对此进行通用查询时,问题出现了:
public class Foo : IDescritible
{
public string Name { get; set; }
string IDescritible.Description
{
get { return this.Name; }
}
}
public class DescriptionMatch<T> : AbstractSpecification<T>
where T : IDescritible
{
public string Query { get; set; }
public DescriptionMatch(string query)
{
this.Query = query;
}
public override Expression<Func<T, bool>> IsSatisfiedBy()
{
return x => x.Description.Contains(Query);
}
}
运行时,EntityFramework 无法将属性 get(方法调用)转换为 SQL 表达式。
然后我尝试在类中定义一个表达式,如下所示:
public interface IDescritible<T> where T: IDescritible<T>
{
Expression<Func<T, string>> DescriptionExpression { get; }
}
public class Foo : IDescritible<Foo>
{
public string Name { get; set; }
public Expression<Func<Foo, string>> DescriptionExpression
{
get { return x => x.Name; }
}
}
public class DescriptionMatch<T> : AbstractSpecification<T> where T : IDescritible<T>
{
public string Query { get; set; }
public DescriptionMatch(string query)
{
this.Query = query;
}
public override Expression<Func<T, bool>> IsSatisfiedBy()
{
Expression<Func<T, bool>> combinedExpression = x => x.DescriptionExpression.Invoke(x).Contains(this.Query);
return combinedExpression.Expand();
}
}
但是当它执行 .Expand() 时会引发异常:无法将类型为“System.Linq.Expressions.PropertyExpression”的对象转换为类型“System.Linq.Expressions.LambdaExpression”。
然后我发现 LinqKit 只支持扩展本地定义的表达式(如本问题所述),并且有一些非官方的代码编写来解决这些问题(本问题的答案)。
但是,当我修改 LinqKit 库以尝试在第二个问题中提出的任一解决方案时,它开始抛出:从范围 '' 引用的 'Foo' 类型的变量 'x',但未定义。
也许这是因为我还没有 Foo 的实例?只有泛型类型参数,这就是为什么我不能在局部变量上定义我的表达式。也许有一种方法可以以某种方式将静态表达式定义为“附加”到类中?但是我将无法在通用查询中使用它,将没有接口......
有一种方法可以修改 LinqKit,以便我可以构建在接口的显式实现上定义的表达式?或者还有另一种方法可以对显式实现的属性进行通用查询?或任何其他解决方案或要研究的事情?
不需要为此使用 LinqKit 或规范模式,但 EntityFramework 是强制性的,重要的是有一个接口/任何其他方式支持“指出”哪个属性是描述属性并在其上制作通用表达式.
先感谢您!