admin管理员组

文章数量:1277273

I have a NRules rule where it cannot match Guid property of a collection in When().Query() but can match/filter if I make the Id property as integer. Is there a way for it to filter even for Guid property?

I tried .ToString() already with ToLower() for the Guid to compare but still to no avail.

Rule:

public class AbcRule : Rule
{
    private readonly ILogger<AbcRule> _logger;

    public AbcRule(ILogger<AbcRule> logger)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }
    public override void Define()
    {
        Guid AbcId = default!;
        IEnumerable<Abc> AbcCollection = default!;
        
        When().Match(() => AbcId)
            .Query(() => AbcCollection, k => k.Match<Abc>(a=>a.AbcId == AbcId).Collect());
            
        Then().Do((IContext ctx) => ctx.Insert(ProcessResult(AbcId, AbcCollection)));
    }

    private AbcResult ProcessResult(Guid abcId, IEnumerable<Abc> abcCollection)
    {
        var count = abcCollection.Count(); //collection is not filtered, still displaying 3 items, expecting 1 only
        
        return new AbcResult();
    }
}

Please see the fact values being passed to the session in the same order: Note the values are really passed to the rule correctly. I could debug and see that it was correct.

var Id = new Guid("450912D8-DB17-494B-B229-B6F12B5D51A2")

IEnumerable<Abc> abcCollection = new[] {
    new Abc{AbcId = new Guid("FEE363FB-B33F-478B-A556-DD089475CD83"), Name = "Hello1"},
    new Abc{AbcId = new Guid("FEE363FB-B33F-478B-A556-DD089475CD83"), Name = "Hello2"},
    new Abc{AbcId = new Guid("450912D8-DB17-494B-B229-B6F12B5D51A2"), Name = "Hello3"}, };

Abc class

public class Abc {
    public Guid AbcId { get; set; }

    public string Name { get; set; } = string.Empty;
}

I have a NRules rule where it cannot match Guid property of a collection in When().Query() but can match/filter if I make the Id property as integer. Is there a way for it to filter even for Guid property?

I tried .ToString() already with ToLower() for the Guid to compare but still to no avail.

Rule:

public class AbcRule : Rule
{
    private readonly ILogger<AbcRule> _logger;

    public AbcRule(ILogger<AbcRule> logger)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }
    public override void Define()
    {
        Guid AbcId = default!;
        IEnumerable<Abc> AbcCollection = default!;
        
        When().Match(() => AbcId)
            .Query(() => AbcCollection, k => k.Match<Abc>(a=>a.AbcId == AbcId).Collect());
            
        Then().Do((IContext ctx) => ctx.Insert(ProcessResult(AbcId, AbcCollection)));
    }

    private AbcResult ProcessResult(Guid abcId, IEnumerable<Abc> abcCollection)
    {
        var count = abcCollection.Count(); //collection is not filtered, still displaying 3 items, expecting 1 only
        
        return new AbcResult();
    }
}

Please see the fact values being passed to the session in the same order: Note the values are really passed to the rule correctly. I could debug and see that it was correct.

var Id = new Guid("450912D8-DB17-494B-B229-B6F12B5D51A2")

IEnumerable<Abc> abcCollection = new[] {
    new Abc{AbcId = new Guid("FEE363FB-B33F-478B-A556-DD089475CD83"), Name = "Hello1"},
    new Abc{AbcId = new Guid("FEE363FB-B33F-478B-A556-DD089475CD83"), Name = "Hello2"},
    new Abc{AbcId = new Guid("450912D8-DB17-494B-B229-B6F12B5D51A2"), Name = "Hello3"}, };

Abc class

public class Abc {
    public Guid AbcId { get; set; }

    public string Name { get; set; } = string.Empty;
}
Share Improve this question edited Feb 26 at 8:07 qme asked Feb 25 at 7:43 qmeqme 3911 gold badge7 silver badges18 bronze badges 2
  • In your Match condition you are comparing the Guids with the AbcId, which is a zero-Guid (default value), and since you don't have a zero-Guid in your fact list, the match does not find anything. Did you mean to compare with some constant Guid value? – Sergiy Nikolayev Commented Feb 25 at 8:23
  • 1 @SergiyNikolayev but I pass the AbcId value as a fact when executing the rule --> new Guid("450912D8-DB17-494B-B229-B6F12B5D51A2") along with the collection values.. so it should be matching right.. because when I made AbcId to int, it was working fine.. How should I fix this? :) – qme Commented Feb 25 at 8:27
Add a comment  | 

1 Answer 1

Reset to default 0

In your example you said you wanted to insert Id Guid as a fact and use it in the AbcRule to filter down facts matched by the Query. In this case, you need to match the Guid fact first, to be able to use it in the Query. Like so:

public class AbcRule : Rule
{
    public override void Define()
    {
        Guid abcId = default!;
        IEnumerable<Abc> abcCollection = default!;

        When()
            .Match(() => abcId)
            .Query(() => abcCollection, k => k
                .Match<Abc>(a => a.Id == abcId)
                .Collect());
            
        Then()
            .Do(ctx => ctx.Insert(ProcessResult(abcId, abcCollection)));
    }

    private AbcResult ProcessResult(Guid abcId, IEnumerable<Abc> abcCollection)
    {
        var count = abcCollection.Count();
        return new AbcResult();
    }
}

And below is example code for inserting the facts into the rules session:

var repository = new RuleRepository();
repository.Load(x => x.From(typeof(AbcRule).Assembly));

var factory = repository.Compile();
var session = factory.CreateSession();

var id = new Guid("450912D8-DB17-494B-B229-B6F12B5D51A2");

IEnumerable<Abc> abcCollection =
[
    new Abc{Id = new Guid("FEE363FB-B33F-478B-A556-DD089475CD83"), Name = "Hello1"},
    new Abc{Id = new Guid("FEE363FB-B33F-478B-A556-DD089475CD83"), Name = "Hello2"},
    new Abc{Id = new Guid("450912D8-DB17-494B-B229-B6F12B5D51A2"), Name = "Hello3"}
];

session.Insert(id);
session.InsertAll(abcCollection);

session.Fire();

本文标签: cNRules rule cannot match on Guid property in When()Query()Stack Overflow