首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >动态LINQ ()返回无效结果

动态LINQ ()返回无效结果
EN

Stack Overflow用户
提问于 2022-09-05 00:27:12
回答 2查看 62关注 0票数 0

问题设置

我试图使用System.Linq.Dynamic.Core包在我的应用程序中实现验证规则,但我遇到了奇怪的行为。我的想法是有能力从应用程序本身创建和管理这些验证规则。因此,我的数据库中有一个ValidationRule对象定义为:

代码语言:javascript
复制
public class ValidationRule {
    public string Description { get; set; }
    public string ErrorMessage { get; set; }
    public short Id { get; set; }
    public bool IsActive { get; set; }
    public string Name { get; set; }
    public string NewExpression { get; set; }
    public string OldExpression { get; set; }
}

NewExpressionOldExpression属性包含我想传递给Any()的动态版本的表达式。ValidationRule对象的唯一重要部分是NameErrorMessageNewExpressionOldExpression,因此我将它们投影到DTO中:

代码语言:javascript
复制
public class ValidationRuleDto {
    public string ErrorMessage { get; set; }
    public string Name { get; set; }
    public string NewExpression { get; set; }
    public string OldExpression { get; set; }
}

然后将此DTO传递给ValidationRuleHandler,以计算正在使用DTO的表达式验证的对象的旧实例和新实例。ValidationRuleHandler看起来如下所示:

代码语言:javascript
复制
public static class ValidationRuleHandler {
    private static readonly ParsingConfig _parsingConfig = new() {
        AreContextKeywordsEnabled = false
    };

    public static ICollection<string> Validate(
        dynamic oldObject,
        dynamic newObject,
        IEnumerable<ValidationRuleDto> rules) => rules.Select(
        _ => {
            var oldResult = new[] {
                oldObject
            }.AsQueryable().Any(_parsingConfig, _.OldExpression);
            var newResult = new[] {
                newObject
            }.AsQueryable().Any(_parsingConfig, _.NewExpression);

            Debug.WriteLine($"Old => {oldObject.StageText} => {_.OldExpression} => {oldResult}");
            Debug.WriteLine($"New => {newObject.StageText} => {_.NewExpression} => {newResult}");
            
            return !(oldResult && newResult)
                ? null
                : $"[{_.Name}] {_.ErrorMessage}";
        }).Where(
        _ => _ != null).ToHashSet();
}

对于传递给Validate()的旧对象和新对象,我将对象投影到一个旧快照(来自数据库)和新快照(从数据库,但应用了更改)DTO。在Validate()中,我将每个对象添加到单个项集合中,并将它们转换为IQueryable,以便使用动态Any()。我在这里的思考过程是,规则的表达式只需计算为真/假结果,因为如果表达式的条件过了,Any()返回true/false,这似乎是最合适的方法。

问题

我遇到的问题是,在运行该应用程序时,我所期望的结果不会发生。作为参考,该应用程序是一个ASP.NET MVC 5 (5.2.9)应用程序,用于获取.NET Framework4.8。但是,当使用LINQPad (5.46.00)测试ValidationRuleHandler时,结果是正确的。例如,当应用程序处理适用于用户的三条验证规则时,Debug语句的输出如下:

  • 旧=>未售出=> (StageText !=“关闭”) => True
  • 新=>关闭=> (StageText == " Closed ") => False
  • 旧=>未售出=> (StageText !=“未售出”) => True 错误
  • 新=>关闭=> (StageText ==“未售出”)和(ReasonNotSoldText == null) => False
  • 旧=>未售出=> (StageText !=“准备发票”) => True
  • 新=>关闭=> (StageText ==“准备发票”)和(PricingMethodText == null) => False

下面是完全相同的验证规则和快照对象(完全相同的值)的LINQPad结果:

  • 旧=>未售出=> (StageText !=“关闭”) => True
  • 新=>关闭=> (StageText ==“关闭”) => True
  • 旧=>未售出=> (StageText !=“未售出”) =>虚假
  • 新=>关闭=> (StageText ==“未售出”)和(ReasonNotSoldText == null) => False
  • 旧=>未售出=> (StageText !=“准备发票”) => True
  • 新=>关闭=> (StageText ==“准备发票”)和(PricingMethodText == null) => False

正如您所看到的,当从ValidationRuleHandler调用LINQPad时,它正确地计算表达式,但是当从应用程序处理时,这是错误的。

我搞不懂它为什么会这样。仔细想想,我看不出有什么问题,LINQPad的表现也和预期的一样,但应用程序没有问题,我也不知道还能做什么。如果有人有任何建议,我会很感激的。我也愿意接受其他的建议,以实现同样的目标,如果有人必须处理类似的事情以前。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-09-08 00:07:37

因此,经过几个小时的尝试,不同的解决方案,看看它到底在哪里失败,没有什么工作,直到我改变表达式使用Equals()。在此之后立即生效,我不知道为什么这个:(StageText.Equals("Closed"));工作,而这个:(StageText == "Closed");不工作。

当我在LINQPad上测试它而不是在应用程序中测试它的时候,我仍然很困惑为什么最初的方法是有效的。@Stef也证实了它的作用,所以我很困惑。也许这与从数据库中提取快照值有关,还是与从数据库中提取验证规则表达式有关?

无论如何,它适用于Equals(),所以我开始使用它。

票数 0
EN

Stack Overflow用户

发布于 2022-09-06 17:41:05

在创建.NET完整Framework4.8控制台应用程序时,使用以下示例代码:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;

namespace ConsoleApp48DynamicLinq
{
    public class ValidationRule
    {
        public string Description { get; set; }
        public string ErrorMessage { get; set; }
        public short Id { get; set; }
        public bool IsActive { get; set; }
        public string Name { get; set; }
        public string NewExpression { get; set; }
        public string OldExpression { get; set; }
    }

    public class ValidationRuleDto
    {
        public string ErrorMessage { get; set; }
        public string Name { get; set; }
        public string NewExpression { get; set; }
        public string OldExpression { get; set; }
    }

    public class Test
    {
        public string StageText { get; set; }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            var old = new Test
            {
                StageText = "Not Sold"
            };

            var @new = new Test
            {
                StageText = "Closed"
            };

            var validation = new ValidationRuleDto
            {
                OldExpression = "(StageText != \"Closed\")",
                NewExpression = "(StageText == \"Closed\")"
            };

            var validations = new[] { validation };

            ValidationRuleHandler.Validate(old, @new, validations);
        }

        public static class ValidationRuleHandler
        {
            private static readonly ParsingConfig ParsingConfig = new ParsingConfig
            {
                AreContextKeywordsEnabled = false
            };

            public static ICollection<string> Validate(
                dynamic oldObject,
                dynamic newObject,
                IEnumerable<ValidationRuleDto> rules) => rules.Select(
                _ =>
                {
                    var oldResult = new[]
                    {
                        oldObject
                    }.AsQueryable().Any(ParsingConfig, _.OldExpression);
                    var newResult = new[]
                    {
                        newObject
                    }.AsQueryable().Any(ParsingConfig, _.NewExpression);

                    Console.WriteLine($"Old => {oldObject.StageText} => {_.OldExpression} => {oldResult}");
                    Console.WriteLine($"New => {newObject.StageText} => {_.NewExpression} => {newResult}");

                    return !(oldResult && newResult) ? null : $"[{_.Name}] {_.ErrorMessage}";
                }).Where(_ => _ != null).ToHashSet();
        }
    }
}

它似乎运转良好:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73603628

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档