相关疑难解决方法(0)

组合多个 Linq 表达式

我正在重构一些代码,试图使其更具自我记录性。当前代码对 OData 服务进行了查询,如下所示:

return context.MessageLog.Where
(
    x => 
    (
        x.Status == MessageStatus.Success 
        || x.Status == MessageStatus.Failure
    ) 
    && x.Direction == MessageDirection.Inbound 
    && x.ResponseDate == new DateTimeOffset(new DateTime(1900, 01, 01))
);
Run Code Online (Sandbox Code Playgroud)

我希望改变这一点以利用 Linq 表达式。
我可以将所有逻辑移动到单个表达式中并运行代码context.MessageLog.Where(MessageIsPendingResponse);。但是,我想为不同的条件创建表达式:(MessageIsProcessed即现在处于成功或失败状态)MessageIsInboundResponseNotYetSent(响应日期为空)。我可以将这些与多个 where 语句结合起来,如下所示:

return context.MessageLog
    .Where(MessageLogExpression.MessageIsProcessed)
    .Where(MessageLogExpression.MessageIsInbound)
    .Where(MessageLogExpression.ResponseNotYetSent);
Run Code Online (Sandbox Code Playgroud)

MessageLogExpression作为我用来包含这些预定义表达式的类)。

问题 1

这是组合语句的最佳方式,还是先过滤错误字段的风险(例如,Linq 是否将所有条件组合成单个查询并允许查询引擎(在 SQL 术语中)确定最佳执行计划;或我们是否强制它首先过滤状态字段?

问题2

以上对于我们AND加入表达式的场景非常有用;但是我们怎么做OR呢?我认为有一些方法可以将这些结合起来,但找不到任何明显的东西。我怀疑这样的事情存在吗?

return context.MessageLog.Where(new OrExpression(MessageIsSuccess,MessageIsFailure));
Run Code Online (Sandbox Code Playgroud)

问题 3

是否有一种在另一个表达式定义中组合表达式的好方法;例如像下面的代码(只有一个编译版本)?

public static Expression<Func<MessageLogRecord, bool>> MessageIsPendingResponse
{
    get
    {
        Expression<Func<MessageLogRecord, bool>> …
Run Code Online (Sandbox Code Playgroud)

c# linq linq-expressions odata

4
推荐指数
1
解决办法
1746
查看次数

在C#中结合BinaryExpression和Expression &lt;Func &lt;dynamic,bool &gt;&gt;

如何结合BinaryExpressionExpression<Func<dynamic / T, bool>>

例如:

void AddGlobalFilter<T>(Expression<Func<T, bool>> expr)
{
    var parameter = Expression.Parameter(type, "t");
    var member = Expression.Property(filter.Parameter, field);
    var constant = Expression.Constant(null);
    var body = Expression.Equal(member, constant);

    var combine = Expression.AndAlso(body, expr);
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试为实体框架(EF)核心定义全局过滤器。问题是我必须手动组合多个过滤器

ModelBuilder如果模型实现IDbDeleted接口,则可以添加一个过滤器。
可以为特定模型手动添加另一个。基本思想是我拥有所有表达式的列表,然后将它们组合:

var expression = listExpressions.First();
foreach (var second in listExpressions.Skip(1))
{
    expression = Expression.AndAlso(expression, second);
}
var lambdaExpression = Expression.Lambda(expression, parameter);
modelBuilder.Entity(item.Key).HasQueryFilter(lambdaExpression);
Run Code Online (Sandbox Code Playgroud)

当然我得到了错误(第一个来自Expression.Equal,第二个来自t => t...):

过滤器表达式't => t …

c# lambda expression-trees entity-framework-core entity-framework-core-2.1

4
推荐指数
1
解决办法
714
查看次数

将Func传递给Where更改返回类型从IQueryable到IEnumerable

我有以下代码;

IQueryable<MyClass> query = listOfObjects.Where(x => x.SomeProp == 1);
Run Code Online (Sandbox Code Playgroud)

我将此传递给一个特定API的方法,该方法期望IQueryable,这很好.

但是,我想动态构建谓词,所以我正在使用它Expression.Lambda来实现这一点,然后我.Compile将它转回一个Func<MyObject, bool>.

我原以为以下会有效;

Func<MyClass, bool> predicate = x => GetPredicate();
IQueryable<MyClass> query = list.Fields.Where(predicate);
Run Code Online (Sandbox Code Playgroud)

但是,传递predicateWhere已经将返回类型更改为IEnumerable<MyClass>,这显然不是API所需的类型.

我做了(天真地)尝试predicate.AsQueryable(),但有问题的API(SharePoint客户端对象模型)失败了,通用的"不支持指定的方法".错误信息.

我不知道这是LINQ提供程序的局限性,但是无论如何......我很想理解为什么将其Func拉出到自己的变量中并将其传入以Where影响类型推断的方式它确实.

c# linq lambda

3
推荐指数
1
解决办法
673
查看次数

.net core - 将 func 列表与单个 func 组合或组合到单个 func

您好,我尝试从由 or 组合的列表中生成单个 Func。

var funcs = new List<Func<User, bool>>()
{
    (u) => u.Id.Equals(entityToFind.Id),
    (u) => u.UserName == entityToFind.UserName,
    (u) => u.Email == entityToFind.Email
};

//TODO: Some magic that funs is euqaly to that:

Func<User, bool> func =  (u) => u.Id.Equals(entityToFind.Id) || u.UserName == entityToFind.UserName || u.Email == entityToFind.Email;
Run Code Online (Sandbox Code Playgroud)

我也用表达式尝试过,就像这样:

private Dictionary<string, Expression<Func<User, bool>>>     private Dictionary<string, Expression<Func<User, bool>>> test(User entityToFind)
{
    return new Dictionary<string, Expression<Func<User, bool>>>() {
        {"Id", (u) => u.Id.Equals(entityToFind.Id) },
        {"Name", (u) => u.UserName == entityToFind.UserName },
        {"Email", …
Run Code Online (Sandbox Code Playgroud)

linq generics func .net-core asp.net-core

3
推荐指数
1
解决办法
692
查看次数

C#如何将两个表达式组合成一个新表达式?

我有两个表达式:

public static Expression<Func<int, bool>> IsDivisibleByFive() {
   return (x) => x % 5 == 0;
}
Run Code Online (Sandbox Code Playgroud)

public static Expression<Func<int, bool>> StartsWithOne() {
   return (x) => x.ToString().StartsWith("1");
}
Run Code Online (Sandbox Code Playgroud)

我想创建一个同时应用两个表达式的新表达式(我的代码在不同的组合中使用相同的表达式):

public static Expression<Func<int, bool>> IsValidExpression() {
   return (x) => IsDivisibleByFive(x) && StartsWithOne(x);
}
Run Code Online (Sandbox Code Playgroud)

然后做:

public static class IntegerExtensions
{
    public static bool IsValid(this int self) 
    {
        return IsValidExpression().Compile()(self);
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的代码中:

if (32.IsValid()) {
   //do something
}
Run Code Online (Sandbox Code Playgroud)

我有很多这样的表达式,我想要定义一次而不是在整个地方复制代码.

谢谢.

c# linq lambda expression

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

将 IQueryables 的“列表”应用到目标?

我有这个想法来创建一个执行不同类型操作的 IQueryables 的“列表”。

所以基本上:

var query1 = Enumerable.Empty<Person>().AsQueryable().Where(e => e.Name == "Ronald");
var query2 = Enumerable.Empty<Person>().AsQueryable().Where(e => e.Age == 43);
var query3 = Enumerable.Empty<Person>().AsQueryable().Select(e => e.EyeColor);

var listOfQueries = new List<IQueryable<Person>
{
    query1,
    query2,
    query3
};
Run Code Online (Sandbox Code Playgroud)

现在,我也有这个充满“Persons”的 DbSet,我想“应用”针对该 DbSet 的所有查询。我该怎么做呢?有可能吗?

更新的示例:

        var personQueryFactory = new PersonQueryFactory();
        var personQueryByFirstname = personQueryFactory.CreateQueryByFirstname("Ronald");           //Query by Firstname.
        var personQueryByAge = personQueryFactory.CreateQueryByAge(42);                             //Query by age.
        var personQueryByHasChildWithAgeOver = personQueryFactory.CreateQueryByChildAgeOver(25);    //Query using a "join" to the child-relationship.
        var personQuerySkip = personQueryFactory.Take(5);                                           //Only get the 5 first …
Run Code Online (Sandbox Code Playgroud)

c# entity-framework iqueryable

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

如何在 linq 中追加表达式?

网络核心应用程序。我实现了一个通用存储库模式。我正在尝试实现一些过滤功能。我有下面的代码。

var param = Expression.Parameter(typeof(SiteAssessmentRequest), "x");
Expression<Func<SiteAssessmentRequest, bool>> query;
query = x => x.CreatedBy == request.Userid || x.AssignedTo == request.Userid;
Expression body = Expression.Invoke(query, param);
if (request.Client != null && request.Client.Length != 0)
            {
                Expression<Func<SiteAssessmentRequest, bool>> internalQuery = x => request.Client.Contains(x.Client);
                body = Expression.AndAlso(Expression.Invoke(query, param), Expression.Invoke(internalQuery, param));
            }

            if (request.CountryId != null && request.CountryId.Length != 0)
            {
                Expression<Func<SiteAssessmentRequest, bool>> internalQuery = x => request.CountryId.Contains(x.CountryId);
                body = Expression.AndAlso(Expression.Invoke(query, param), Expression.Invoke(internalQuery, param));
            }

            if (request.SiteName != null && request.SiteName.Length != 0)
            { …
Run Code Online (Sandbox Code Playgroud)

c# linq asp.net generics repository-pattern

-1
推荐指数
1
解决办法
3121
查看次数