Skip to content

UCAST integration for LINQ. Uses LINQ Expression ASTs for efficient queries.

License

Notifications You must be signed in to change notification settings

open-policy-agent/ucast-linq

Repository files navigation

EOPA Data Filters Support - C# UCAST integration for LINQ

License NuGet Version

Important

The reference documentation for this library is available at https://open-policy-agent.github.io/ucast-linq

Overview

This library allows users to integrate dynamic data filtering rules into LINQ queries that are driven by policies written in Rego.

Below is a high-level sequence diagram of the process:

sequenceDiagram
    C# Application ->>+ OPA: Compile API Request
    OPA ->>- C# Application: UCAST Result

    C# Application ->> C# Application: Translate UCAST to LINQ Query

    participant Database@{ "type" : "database" }
    C# Application ->>+ Database: LINQ Query
    Database ->>- C# Application: Query Results
Loading

See the Development Workflow docs for more details.

Installation

Nuget

dotnet add package OpenPolicyAgent.Ucast.Linq

Example Usage

Let's assume that we have a collection of random integers, and wish to filter them with a LINQ query using multiple criteria:

using System;
using System.Linq;

public record SimpleRecord(int Value);

var numbers = new int[] { -1523, 1894, -456, 789, -1002, 345, -1789, 567, 1234, -890, 123, -1456, 1678, -234, 567, -1890, 901, -345, 1567, -789 };
var collection = numbers.Select(n => new SimpleRecord(n)).ToList();
var results = collection.Where(x => x.Value >= 1500 || (x.Value < 400 && (x.Value > 0 || x.Value < -1500)))
                        .OrderBy(x => x.Value)
                        .ToList();

Console.WriteLine(string.Join("\n", results));
Output
SimpleRecord { Value = -1890 }
SimpleRecord { Value = -1789 }
SimpleRecord { Value = -1523 }
SimpleRecord { Value = 123 }
SimpleRecord { Value = 345 }
SimpleRecord { Value = 1567 }
SimpleRecord { Value = 1678 }
SimpleRecord { Value = 1894 }

Using this library, the same filters can be constructed dynamically using UCAST expressions (which can be deserialized from JSON):

using System;
using System.Linq;
using OpenPolicyAgent.Ucast.Linq;

public record SimpleRecord(int Value);

var conditions = new UCASTNode { Type = "compound", Op = "or", Value = new List<UCASTNode>{
    new UCASTNode { Type = "field", Op = "ge", Field = "r.value", Value = 1500 },
    new UCASTNode { Type = "compound", Op = "and", Value = new List<UCASTNode>{
        new UCASTNode { Type = "field", Op = "lt", Field = "r.value", Value = 400 },
        new UCASTNode { Type = "compound", Op = "or", Value = new List<UCASTNode>{
            new UCASTNode { Type = "field", Op = "gt", Field = "r.value", Value = 0 },
            new UCASTNode { Type = "field", Op = "lt", Field = "r.value", Value = -1500 },
        } },
    } },
} };

var numbers = new int[] { -1523, 1894, -456, 789, -1002, 345, -1789, 567, 1234, -890, 123, -1456, 1678, -234, 567, -1890, 901, -345, 1567, -789 };
var collection = numbers.Select(n => new SimpleRecord(n)).ToList();
var results = collection.AsQueryable()
                        .ApplyUCASTFilter(conditions, new MappingConfiguration<SimpleRecord>(prefix: "r"))
                        .OrderBy(x => x.Value)
                        .ToList();

Console.WriteLine(string.Join("\n", results));
Output
SimpleRecord { Value = -1890 }
SimpleRecord { Value = -1789 }
SimpleRecord { Value = -1523 }
SimpleRecord { Value = 123 }
SimpleRecord { Value = 345 }
SimpleRecord { Value = 1567 }
SimpleRecord { Value = 1678 }
SimpleRecord { Value = 1894 }

Community

For questions, discussions, and announcements, please join the OPA community on Slack!

About

UCAST integration for LINQ. Uses LINQ Expression ASTs for efficient queries.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •