0

I have an excel with the number of records. I want to apply Nrule on it. I want to match two rows and apply rules on them and check whether it is breaking it or not. for example :

Id Date Desc
1 12/31/21 Somethings
1 12/31/21 Anything
2 1/1/22 Lorem Epsum

Rule : "Somethings" and "Anything" should not come on same date.

Hence, here it is breaking a rule. How to right it in NRule?

  • Your question is unclear. Do the records in the Excel file represent data or rules or both? If it's just data, load it into a domain model and use those objects as facts with NRules (there are plenty of examples on SO of how to load data from Excel). If you are trying to encode rules in Excel, that is not supported in NRules. – Sergiy Nikolayev Jan 05 '22 at 04:18
  • Records in Excel represents data not rules – Vatsal Agravat Jan 07 '22 at 04:27
  • Then, as I mentioned, load the data from Excel to a domain model (if it's a csv file can just use something like CsvHelper). Then write your rules in terms of that domain model. – Sergiy Nikolayev Jan 07 '22 at 05:13

1 Answers1

0

If Excel file is a CSV, you can use CsvHelper to read the data into a domain model. If it's truly an Excel document, there are articles on SO outlining how to load data from Excel.

Using CsvHelper and NRules, here is one way how to load the data and implement the requested rule.

using System.Globalization;
using CsvHelper;
using CsvHelper.Configuration;
using NRules;
using NRules.Fluent;
using NRules.Fluent.Dsl;

//Read records from CSV file
using var reader = new StreamReader(@"Data.csv");
var configuration = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = true };
using var csv = new CsvReader(reader, configuration);
var records = csv.GetRecords<Record>();

//Load rule(s) and compile into NRules session
var repository = new RuleRepository();
repository.Load(x => x.From(typeof(SameDateRule)));
var factory = repository.Compile();
var session = factory.CreateSession();

//Insert records as facts and fire the rules
session.InsertAll(records);
session.Fire();

//Get results from the session
var violations = session.Query<Violation>();
Console.WriteLine($"Found {violations.Count()} violation(s)");

public class Record
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    [CsvHelper.Configuration.Attributes.Name("Desc")]
    public string Description { get; set; }
}

public class Violation
{
    public Violation(IGrouping<DateTime, Record> records)
    {
        Date = records.Key;
        Records = records.ToArray();
    }

    public DateTime Date { get; }
    public IReadOnlyCollection<Record> Records { get; }
}

public class SameDateRule : Rule
{
    public override void Define()
    {
        IGrouping<DateTime, Record> records = default;

        When()
            .Query(() => records, q => q
                .Match<Record>()
                .GroupBy(x => x.Date)
                .Where(g => g.Any(x => x.Description == "Somethings")
                         && g.Any(x => x.Description == "Anything")));

        Then()
            .Do(ctx => ctx.Insert(new Violation(records)));
    }
}
Sergiy Nikolayev
  • 702
  • 4
  • 13