标签: linq-expressions

将LINQ表达式传递给另一个QueryProvider

我有一个简单的自定义QueryProvider,它接受一个表达式,将其转换为SQL并查询sql数据库.

我想在QueryProvider中创建一个小缓存来存储常用对象,这样就可以在没有数据库命中的情况下进行检索.

QueryProvider具有该方法

public object Execute(System.Linq.Expressions.Expression expression)
{
    /// Builds an SQL statement from the expression, 
    /// executes it and returns matching objects
}
Run Code Online (Sandbox Code Playgroud)

缓存作为此QueryProvider类中的字段而存在,并且是一个简单的通用List.

如果我使用List.AsQueryable方法并将上面的表达式传递给List.AsQueryable的Provider的Execute方法,它就不能按预期工作.看起来当表达式被编译时,初始QueryProvider成为一个不可或缺的部分.

是否可以将表达式传递给后续的QueryProvider并根据需要执行表达式?

调用代码看起来模糊如下:

public class QueryProvider<Entity>()
{
    private List<TEntity> cache = new List<Entity>();

    public object Execute(System.Linq.Expressions.Expression expression)
    {
        /// check whether expression expects single or multiple result
        bool isSingle = true;

        if (isSingle)
        {
            var result = this.cache.AsQueryable<Entity>().Provider.Execute(expression);
            if (result != null) 
                return result;
        }

        /// cache failed, hit database
        var qt = new QueryTranslator(); …
Run Code Online (Sandbox Code Playgroud)

c# linq linq-expressions

13
推荐指数
1
解决办法
2840
查看次数

如何在EF Where()子句中使用Predicate <T>?

我正在尝试在我的EF过滤代码中使用谓词.

这有效:

IQueryable<Customer> filtered = customers.Where(x => x.HasMoney && x.WantsProduct);
Run Code Online (Sandbox Code Playgroud)

但是这个:

Predicate<T> hasMoney = x => x.HasMoney;
Predicate<T> wantsProduct = x => x.WantsProduct;
IQueryable<Customer> filtered = customers.Where(x => hasMoney(x) && wantsProduct(x));
Run Code Online (Sandbox Code Playgroud)

在运行时失败:

The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
Run Code Online (Sandbox Code Playgroud)

我不能使用第一个选项,因为这是一个简单的例子,实际上,我正在尝试将一堆谓词组合在一起(使用和不使用等)以实现我想要的功能.

如何让EF Linq提供程序"理解"我的谓词?

如果我使用a,我会得到相同的结果Func<T, bool>.它适用于Expression<Func<T>>,但我不能将表达式组合在一起进行复杂的过滤.如果可能的话,我宁愿避免使用外部库.

更新:
如果无法做到这一点,我有什么选择?也许以某种方式组合/或/和表达表达式以达到同样的效果?

c# linq entity-framework linq-expressions

12
推荐指数
1
解决办法
6635
查看次数

动态添加新的lambda表达式以创建过滤器

我需要对ObjectSet进行一些过滤,以通过这样做获取我需要的实体:

query = this.ObjectSet.Where(x => x.TypeId == 3); // this is just an example;
Run Code Online (Sandbox Code Playgroud)

稍后在代码中(以及在启动延迟执行之前)我再次过滤查询,如下所示:

query = query.Where(<another lambda here ...>);
Run Code Online (Sandbox Code Playgroud)

到目前为止,这很有效.

这是我的问题:

实体包含DateFrom属性和DateTo属性,它们都是DataTime类型.它们代表了一段时间.

我需要过滤的实体只拿到那些一个部分集合时间段.集合的句点不一定是连续的,因此,检索实体的逻辑看起来像这样:

entities.Where(x => x.DateFrom >= Period1.DateFrom and x.DateTo <= Period1.DateTo)
||
entities.Where(x => x.DateFrom >= Period2.DateFrom and x.DateTo <= Period2.DateTo)
||
Run Code Online (Sandbox Code Playgroud)

......以及集合中所有时期的不断变化.

我试过这样做:

foreach (var ratePeriod in ratePeriods)
{
    var period = ratePeriod;

    query = query.Where(de =>
        de.Date >= period.DateFrom …
Run Code Online (Sandbox Code Playgroud)

c# linq linq-to-entities linq-expressions

12
推荐指数
1
解决办法
2万
查看次数

从作用域引用的'Product'类型的变量'x',但未定义

我有一个Product在类库项目中命名的类.我SubSonic SimpleRepository用来坚持对象.我在Product课堂上有如下方法:

public static IList<Product> Load(Expression<Func<Product, bool>> expression)
{
    var rep=RepoHelper.GetRepo("ConStr");
    var products = rep.Find(expression);
    return products.ToList();
}
Run Code Online (Sandbox Code Playgroud)

我正在调用这个函数:

private void BindData()
{
    var list = Product.Load(x => x.Active);//Active is of type bool
    rptrItems.DataSource = list;
    rptrItems.DataBind();
}
Run Code Online (Sandbox Code Playgroud)

调用LoadBindData引发异常:

variable 'x' of type 'Product' referenced from scope '', but it is not defined
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题.

编辑: - 通过单步执行SubSonic代码,我发现该函数抛出了错误

private static Expression Evaluate(Expression e)
{
    if(e.NodeType == ExpressionType.Constant)
        return e; …
Run Code Online (Sandbox Code Playgroud)

c# lambda subsonic3 linq-expressions

11
推荐指数
1
解决办法
9284
查看次数

Linq表达式如何确定平等?

我正在考虑使用Linq Expression作为字典中的键.但是,我担心我会得到奇怪的结果,因为我不知道Linq表达式如何确定Equality.

派生自Expression的类是否比较值相等或引用相等?或者换句话说,

        Expression<Func<object>> first = () => new object(); 
        Expression<Func<object>> second = ()=>new object();
        bool AreTheyEqual = first == second;
Run Code Online (Sandbox Code Playgroud)

c# linq lambda expression linq-expressions

11
推荐指数
1
解决办法
2049
查看次数

可靠地检测C#表达式树中的编译器生成的类

我正在构建一个C#表达式到Javascript的转换器,沿着Linq-to-SQL的路线,但我遇到了编译器生成的表达式树的问题.

我遇到的特殊问题是处理MemberExpression编译器生成的值,但是没有CompilerGeneratedAttribute在其类型上指定的值.

这是我一直在尝试的简化版本:

void ProcessMemberExpression(MemberExpression memberX) {
    var expression = memberX.Expression;
    var expressionType = expression.Type;
    var customAttributes = expressionType.GetCustomAttributes(true);
    var expressionTypeIsCompilerGenerated = customAttributes.Any(x => x is CompilerGeneratedAttribute);
    if (expressionTypeIsCompilerGenerated) {
        var memberExpressionValue = Expression.Lambda(memberX).Compile().DynamicInvoke();
        ... do stuff ...
    }
    else {
        ... do other stuff ...
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我打开了一个Visual Studio调试会话,我发现它(在立即窗口中运行):

expressionType.Name
"<>c__DisplayClass64"
expressionType.GetCustomAttributes(true)
{object[0]}
expressionType.GetCustomAttributes(true).Length
0
Run Code Online (Sandbox Code Playgroud)

所以我在这里有一个显然是编译器生成的类,没有自定义属性,因此没有CompilerGeneratedAttribute!因此,do other stuff当我打算公正时,我的代码将会do stuff.

如果有人能帮助我,我会非常感激.如果可能的话,我真的宁愿做任何肮脏的事情就像匹配类似的expressionType.Name东西<>.*__DisplayClass.

.net c# linq expression-trees linq-expressions

11
推荐指数
1
解决办法
1220
查看次数

具有null属性的嵌套属性上的动态linq顺序

我正在使用这个动态的linq orderby函数,我从这里得到.

这适用于嵌套属性,所以我可以这样做:

var result = data.OrderBy("SomeProperty.NestedProperty");
Run Code Online (Sandbox Code Playgroud)

问题是,如果SomeProperty为null,那么在NestedProperty上执行OrderBy会抛出臭名昭着的"对象引用未设置为对象的实例".

我的猜测是我需要自定义以下行来处理异常:

expr = Expression.Property(expr, pi);

// Or

LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);    
Run Code Online (Sandbox Code Playgroud)

我考虑创建一个语句体,在最坏的情况下我可以使用try catch,但这不起作用,因为你不能在orderby linq语句中使用语句体:"带有语句体的lambda表达式无法转换为表达树"

我迷失在这里,有关如何实现这一目标的任何建议?

顺便说一句,这是针对Linq to Objects,而不是数据库相关的.

c# linq linq-expressions

11
推荐指数
2
解决办法
4634
查看次数

在System.Linq.Expressions中切换没有案例(但默认情况下)

我试图用System.Linq.Expressions创建一个switch表达式:

var value = Expression.Parameter(typeof(int));
var defaultBody = Expression.Constant(0);
var cases1 = new[] { Expression.SwitchCase(Expression.Constant(1), Expression.Constant(1)), };
var cases2 = new SwitchCase[0];
var switch1 = Expression.Switch(value, defaultBody, cases1);
var switch2 = Expression.Switch(value, defaultBody, cases2);
Run Code Online (Sandbox Code Playgroud)

但在最后一行我得到一个ArgumentException:

需要非空收集.参数名称:案例

这个例外的原因是什么?这可能是Expression.Switch(...)中的一个错误?

在C#中,只有"默认"部分的开关是正确的:

switch(expr) {
default:
  return 0;
}//switch
Run Code Online (Sandbox Code Playgroud)

UPD:我已经向GitHub上的CoreFX回购提交了一个问题

.net c# linq-expressions

11
推荐指数
1
解决办法
562
查看次数

将lambda表达式转换为用于缓存的唯一键

我已经看过类似这个问题的其他问题,但我找不到任何可行的答案.

我一直在使用以下代码生成唯一键,用于将我的linq查询的结果存储到缓存中.

    string key = ((LambdaExpression)expression).Body.ToString();

    foreach (ParameterExpression param in expression.Parameters)
    {
        string name = param.Name;
        string typeName = param.Type.Name;

        key = key.Replace(name + ".", typeName + ".");
    }

    return key;
Run Code Online (Sandbox Code Playgroud)

它似乎适用于包含整数或布尔值的简单查询,但是当我的查询包含嵌套的常量表达式时,例如

// Get all the crops on a farm where the slug matches the given slug.
(x => x.Crops.Any(y => slug == y.Slug) && x.Deleted == false)
Run Code Online (Sandbox Code Playgroud)

返回的密钥是:

(True AndAlso(Farm.Crops.Any(y =>(value(OzFarmGuide.Controllers.FarmController + <> c__DisplayClassd).slug == y.Slug))AndAlso(Farm.Deleted == False)))

正如您所看到的,我传递的任何裁剪名称都会给出相同的关键结果.有没有办法可以提取给定参数的值,以便我可以区分我的查询?

还转换y为说出正确的类型名称会很好.....

c# linq caching linq-expressions

10
推荐指数
1
解决办法
3617
查看次数

从类型动态获取类属性值

我正在尝试编写一个方法,在具有特定自定义属性的程序集中查找所有类型.我还需要能够提供匹配的字符串值.需要注意的是,我希望能够在任何类上运行它并返回任何值.

例如:我想执行这样的调用

Type tTest = TypeFinder.GetTypesWithAttributeValue(Assembly.Load("MyAssembly"), typeof(DiagnosticTestAttribute), "TestName", "EmailTest");
Run Code Online (Sandbox Code Playgroud)

到目前为止我的方法看起来像这样:

public static Type GetTypesWithAttributeValue(Assembly aAssembly, Type tAttribute, string sPropertyName, object oValue)
{
    object oReturn = null;
    foreach (Type type in aAssembly.GetTypes())
    {
        foreach (object oTemp in type.GetCustomAttributes(tAttribute, true))
        {
            //if the attribute we are looking for matches
            //the value we are looking for, return the current type.
        }
    }
    return typeof(string); //otherwise return a string type
}
Run Code Online (Sandbox Code Playgroud)

我的属性看起来像这样:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class DiagnosticTestAttribute : Attribute
{
    private string _sTestName …
Run Code Online (Sandbox Code Playgroud)

c# reflection custom-attributes linq-expressions

10
推荐指数
1
解决办法
1万
查看次数