EntityMatcher 1.0.0

dotnet add package EntityMatcher --version 1.0.0
                    
NuGet\Install-Package EntityMatcher -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EntityMatcher" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EntityMatcher" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="EntityMatcher" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EntityMatcher --version 1.0.0
                    
#r "nuget: EntityMatcher, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EntityMatcher@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EntityMatcher&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=EntityMatcher&version=1.0.0
                    
Install as a Cake Tool

EntityMatcher

A .NET library for deterministic, offline entity matching across domains. Compares names, addresses, phones, dates, organizations, countries, and arbitrary text/numeric fields using alias resolution, fuzzy scoring, and tolerance-based matching. Supports single-pair comparison, record-level profile matching, and high-performance set matching.

Features

  • 12 domain matchers: GivenName, FamilyName, TitleOrCredential, OrganizationName, USStreetAddress, USStateTerritory, Country, Phone, Date, Exact, Text, Numeric
  • Alias resolution: 278 given-name groups (947 names), 249 ISO 3166 countries, 62 US states/territories, 32 title/credential groups, 200+ USPS suffix/unit mappings
  • Fuzzy scoring: Jaro-Winkler, Damerau-Levenshtein, token-set similarity
  • Tolerance matching: Date (configurable day window), Numeric (absolute or percentage)
  • Record-level profiles: Required/Optional/Veto field semantics with weighted scoring
  • Set matching (net8.0+): Ad-hoc lookup, 1:1 enrollment comparison, 1:many matching, hybrid exact+fuzzy, confidence-ranked pool matching
  • Custom matchers: Extensible via IFieldMatcher -- add your own domain-specific comparison logic
  • Zero runtime dependencies: Core package targets netstandard2.0, no I/O, no reflection, no network calls
  • Thread-safe: Immutable engine, concurrent-safe set matcher

Quick Start

using EntityMatcher.Core;

// Build an engine (loads compiled-in alias data automatically)
var engine = new EntityMatcherEngineBuilder().Build();

// Compare individual fields
var result = engine.Compare(FieldKind.GivenName, "Bill", "William");
// result.State == Match, Method == Alias, Score == 100

// Fuzzy text matching
engine.Compare(FieldKind.Text, "Accounting", "Acounting");
// Match via Jaro-Winkler fuzzy, score ~97

// Numeric with tolerance
engine.Compare(FieldKind.Numeric, "$99.99", "$100.00",
    new MatchOptions { NumericTolerance = 0.05m });
// Match via tolerance scoring

Record-Level Matching

using EntityMatcher.Profiles;

var profile = new MatchProfile<Person>()
    .Require(p => p.LastName, FieldKind.FamilyName)
    .Optional(p => p.FirstName, FieldKind.GivenName, weight: 2m)
    .Optional(p => p.DOB, FieldKind.Date, weight: 1m)
    .Veto(p => p.SSN, FieldKind.Exact)
    .Threshold(85);

var result = profile.Compare(personA, personB, engine);
// result.IsMatch, result.Score, result.Confidence
// result.Explain() for human-readable breakdown

Set Matching (net8.0+)

using EntityMatcher.SetMatching;

// Build a set matcher for batch operations
var matcher = new EntitySetMatcher<Person, PersonMatchType>(
    databaseRecords, matchDefinitions);

// Ad-hoc lookup against a set
var matches = matcher.FindMatches(incomingRecord, [PersonMatchType.Ssn]);

// 1:1 enrollment comparison with tiered criteria
var result = matcher.CreateTwoWayMatchDictionary(
    enrollmentB,
    tieredCriteria: [[PersonMatchType.Ssn], [PersonMatchType.Name, PersonMatchType.Dob]]);

// 1:many matching (customer to orders)
var multi = matcher.CreateMultiMatchResult(orders, [PersonMatchType.CustomerId]);

// Confidence-ranked pool matching (best matches assigned first, pool drains top-down)
var ranked = matcher.CreateRankedMatchDictionary(
    enrollmentB, profile: fuzzyProfile, engine: engine,
    exactCriteria: [[PersonMatchType.Ssn]]);

// Hybrid: exact dictionary pass + fuzzy profile fallback with blocking
var hybrid = matcher.CreateHybridMatchDictionary(
    enrollmentB,
    exactCriteria: [[PersonMatchType.Ssn]],
    fuzzyProfile: fuzzyProfile,
    engine: engine,
    blockingStrategy: BlockingKeyStrategies.FirstCharOf<Person>(p => p.LastName));

Match Quality

Tested against 10,000 synthetic records with realistic data corruption:

Strategy Clean Moderate Dirty Hostile
SSN only 100% 75% 60% 19%
Tiered (SSN + Name/DOB + Email) 100% 99% 96% 66%
Tiered + Phone 100% 100% 100% 83%
Hybrid (SSN + Fuzzy w/ blocking) 100% 99% 97% 91%
Hybrid (SSN + Email + Phone + Fuzzy) 100% 100% 100% 97%

Projects

Project Target Description
EntityMatcher netstandard2.0 + net8.0 + net9.0 Core library
EntityMatcher.DependencyInjection netstandard2.0 Optional DI companion
EntityMatcher.UnitTests net10.0 Unit + acceptance tests
EntityMatcher.ProfileTests net10.0 Profile matching tests
EntityMatcher.RegressionTests net10.0 False-positive + concurrency regression tests
EntityMatcher.Benchmarks net10.0 BenchmarkDotNet performance suite

Data Sources

All alias data is compiled directly into C# source code (zero I/O at runtime):

  • Given names: 278 groups from onyxrev/common_nickname_csv (public domain)
  • Countries: 249 entries from ISO 3166-1
  • US States: 62 entries (50 states + DC + territories + military codes)
  • Titles/Credentials: 32 curated groups
  • USPS Suffixes: 200+ entries from USPS Publication 28 (public domain)
  • USPS Secondary Units: 24 entries from USPS Publication 28

Installation

dotnet add package EntityMatcher
dotnet add package EntityMatcher.DependencyInjection  # optional, for DI integration

Documentation

  • Getting Started -- Installation, quick start, configuration
  • Field Matchers -- All 12 domain matchers with examples
  • Profiles -- Record-level matching with Required/Optional/Veto fields
  • Set Matching -- Batch operations, 1:1, 1:many, hybrid, ranked matching
  • Custom Matchers -- Extensibility with custom field types
  • Data Sources -- Embedded datasets, adding custom aliases
  • Performance -- Benchmarks, quality report, optimization guidance

Building

dotnet build EntityMatcher.slnx
dotnet test EntityMatcher.slnx

License

MIT

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on EntityMatcher:

Package Downloads
EntityMatcher.DependencyInjection

Microsoft.Extensions.DependencyInjection integration for EntityMatcher. Registers IEntityMatcherEngine as a singleton with optional builder configuration.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 157 4/4/2026