Applying NRules on excel dataset

263 Views Asked by At

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?

1

There are 1 best solutions below

0
On

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)));
    }
}