Avoiding "duplicate declarations" error when using GroupBuilder

57 views
Skip to first unread message

Andrew Stanford

unread,
Nov 26, 2019, 5:35:06 AM11/26/19
to NRules Users
Hi


I saw this post and followed what it said (I think)

The relevant code I have is this;
                var matchedProperty = dbfieldList.Where(w => w.ObjectType == f.ObjectType && w.RuleId == f.RuleId && w.PropertyName == f.PropertyName).ToList();
               
if (matchedProperty != null && matchedProperty.Count > 1)
               
{
                   
//there are multiple conditions for this property so "OR" them
                   
var orGroup = builder.LeftHandSide().Group(GroupType.Or);
                   
PatternBuilder orPattern = orGroup.Pattern(f.ObjectType, f.ObjectType.Name.ToLower());
                   
foreach (var mp in matchedProperty)
                   
{
                       
//where SetCondition builds a lambda expression & returns it
                        orPattern
.Condition(SetCondition(mp, ExpressionMode.TargetValue));
                   
}
                    action
= (ctx) => ProcessAssessmentFieldResult(ctx);
                    builder
.RightHandSide().Action(action);
                    ruleList
.Add(builder.Build());
                   
continue;
               
}

The error is raised on ruleList.Add(builder.Build()); and it is caused in a case where we are saying "Customer employment status is 'Permanent fulltime' OR 'Permanent Part-time' AND employment term < 12 months". The error is triggered in ElementValidator.ValidateUniqueDeclarations saying that customer is duplicated.



Thanks
Andrew

Andrew Stanford

unread,
Nov 26, 2019, 2:48:05 PM11/26/19
to NRules Users
I did try this - thinking the name "customer" being used twice was an issue;
                    var orGroup = builder.LeftHandSide().Group(GroupType.Or);
                    int counter = 1;
                    foreach (var mp in matchedProperty)
                    {
                        //where SetCondition builds a lambda expression & returns it
                        PatternBuilder orPattern = orGroup.Pattern(f.ObjectType, f.ObjectType.Name.ToLower() + counter);
                        orPattern.Condition(SetCondition(mp, ExpressionMode.TargetValue));
                        counter++;
                    }

While this does stop the build error - it doesn't actually work as a customer with matching facts doesn't match. It doesn't seem to like that I am using the same property twice. So adding fact "Customer.EmploymentStatus=='Permanent Fulltime' OR Customer.EmploymentStatus=='Permanent Parttime'" - then checking a customer with employment status "Permanent Fulltime" doesn't match

Larry LeBron

unread,
Nov 26, 2019, 3:35:31 PM11/26/19
to NRules Users
I haven't worked with the RuleBuilder, but have worked with Fluent DSL rule declarations a good deal.

Could you write up a version of your rule in the Fluent DSL and see if you can build it?

This might help illuminate the issue.

I am seemingly able to build an Or group with multiple match clauses into the same variable name. So I'm not sure exactly what is giving you a problem in your example code.

Andrew Stanford

unread,
Nov 28, 2019, 5:47:18 AM11/28/19
to NRules Users
Thanks Larry. 

I altered the code slightly and got the "OR" working OK;
                var matchedProperty = dbfieldList.Where(w => w.ObjectType == f.ObjectType && w.RuleId == f.RuleId && w.PropertyName == f.PropertyName).ToList();
               
if (matchedProperty != null && matchedProperty.Count > 1)
               
{
                   
//there are multiple conditions for this property so "OR" them
                   
var orGroup = builder.LeftHandSide().Group(GroupType.Or);

                   
foreach (var mp in matchedProperty)
                   
{

                        builder
.Property("AssessmentField" + "-" + mp.AssessmentFieldId, mp); //store field definition

                       
//where SetCondition builds a lambda expression & returns it

                       
PatternBuilder orPattern = orGroup.Pattern(f.ObjectType, f.ObjectType.Name.ToLower());

                        orPattern
.Condition(SetCondition(mp, ExpressionMode.TargetValue));
                   
}
                   
//on completion add to the processedMatchedProperty list to prevent it being processed again
                    processedMatchedProperties
.AddRange(matchedProperty);

                    action
=
                   
(ctx) => ProcessAssessmentFieldResult(ctx);
                    builder
.RightHandSide().Action(action);
                    ruleList
.Add(builder.Build());
               
}


I have another issue now where I cannot tell which field/value was true in the action? I wondered about adding something to help identify the winning part of the "OR" group to the action definition... but that won't help as it is the same value once it arrives in the callback method. 


Thanks,
Andrew


Reply all
Reply to author
Forward
0 new messages