DeepDiff 1.12.0

dotnet add package DeepDiff --version 1.12.0
                    
NuGet\Install-Package DeepDiff -Version 1.12.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="DeepDiff" Version="1.12.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DeepDiff" Version="1.12.0" />
                    
Directory.Packages.props
<PackageReference Include="DeepDiff" />
                    
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 DeepDiff --version 1.12.0
                    
#r "nuget: DeepDiff, 1.12.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 DeepDiff@1.12.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=DeepDiff&version=1.12.0
                    
Install as a Cake Addin
#tool nuget:?package=DeepDiff&version=1.12.0
                    
Install as a Cake Tool

Breaking changes

1.12.0

  • Hashtable and PrecompiledComparer are now mandatory

1.11.1

  • By default, DeepDiff will now check for duplicate keys in entities and nested entities. You can disable this behavior using SetCheckDuplicateKeys(false) in MergeSingle, MergeMany, CompareSingle and CompareMany configuration

1.11.0

  • IOperationListener are now mandatory when using CompareSingle and CompareMany methods

1.10.0

  • to configure an entity, you must now use the ConfigureEntity<TEntity>() method instead of Entity<TEntity>()

Example

How do I get started

First configure DeepDiff to register what types you want to compare, in the startup of your application

var diffConfiguration = new DiffConfiguration();
diffConfiguration.ConfigureEntity<Entity>()                       // configure Entity type
   .HasKey(x => new { x.StartsOn, x.Name })                       // business key
   .HasValues(x => new { x.Price, x.Volume })                     // properties to compare for update (and copy on update)
   .HasMany(x => x.SubEntities)                                   // one-to-many relation
   .OnInsert(cfg => cfg                                           // operations to perform on insert
          .SetValue(x => x.PersistChange, PersistChange.Insert))  //     change PersistChange property to Insert
   .OnUpdate(cfg => cfg                                           // operations to perform on update
          .SetValue(x => x.PersistChange, PersistChange.Update))  //     change PersistChange property to Update
   .OnDelete(cfg => cfg                                           // operations to perform on delete
          .SetValue(x => x.PersistChange, PersistChange.Delete)); //     change PersistChange property to Delete

diffConfiguration.ConfigureEntity<SubEntity>()                    // configure SubEntity type
   .HasKey(x => x.SubName)                                        // business key
   .HasValues(x => x.Energy)                                      // property to compare for update (and copy on update)
   .OnInsert(cfg => cfg                                           // operations to perform on insert
          .SetValue(x => x.PersistChange, PersistChange.Insert))  //     change PersistChange property to Insert
   .OnUpdate(cfg => cfg                                           // operations to perform on update
          .SetValue(x => x.PersistChange, PersistChange.Update)   //     change PersistChange property to Update
          .CopyValues(x => x.Description)                         //     copy Description property from new to existing entity
   .OnDelete(cfg => cfg                                           // operations to perform on delete
          .SetValue(x => x.PersistChange, PersistChange.Delete))  //     change PersistChange property to Delete
   .Ignore(x => new { x.Entity, x.EntityId} );                    //     foreign key and navigation are not relevant for diff

var deepDiff = diffConfiguration.CreateDeepDiff();                // finalize configuration

Then in your application code, this will detect insert/update/delete between existing and new entities. In case of update, properties will be copied from new to existing entity. PersistChange property will be set accordingly, so you can persist changes in your database and in case of update Description property will also be copied from new to existing sub entity.

var resultEntities = deepDiff.MergeMany(existingEntities, newEntities); // resultEntities will contain 'merged' entities

Example entities definition

public class Entity
{
  public Guid Id { get; set; } // DB Key
  public DateTime StartsOn { get; set; } // Business Key
  public string Name { get; set; } // Business Key
  public decimal Price { get; set; }
  public int Volume { get; set; }
  public PersistChange PersistChange { get; set; }
  public List<SubEntity> SubEntities { get; set; }
}

public class SubEntity
{
  public Guid Id { get; set; } // DB Key
  public string SubName { get; set; } // Business Key
  public int Energy { get; set; }
  public string Description { get; set; } // Not part of key or values, will not be used in diff
  public PersistChange PersistChange { get; set; }
  public Guid EntityId { get; set; } // Foreign Key
  public Entity Entity { get; set; } // Navigation property
}

public enum PersistChange
{
  None,
  Insert,
  Update,
  Delete
}

Entity Configuration

HasKey

Defines properties used to compare and detect an insert and a delete. Mandatory unless NoKey has been defined

IEntityConfiguration<TEntity> HasKey<TKey>(Expression<Func<TEntity, TKey>> keyExpression)
IEntityConfiguration<TEntity> HasKey<TKey>(Expression<Func<TEntity, TKey>> keyExpression, Action<IKeyConfiguration<TEntity>> keyConfigurationAction)

HasValues

Defines properties used to detect an update in case keys are identical

IEntityConfiguration<TEntity> HasValues<TValue>(Expression<Func<TEntity, TValue>> valuesExpression)
IEntityConfiguration<TEntity> HasValues<TValue>(Expression<Func<TEntity, TValue>> valuesExpression, Action<IValuesConfiguration<TEntity>> valuesConfigurationAction)

HasOne

Defines property to navigate to a single child

IEntityConfiguration<TEntity> HasOne<TChildEntity>(Expression<Func<TEntity, TChildEntity>> navigationPropertyExpression)
IEntityConfiguration<TEntity> HasOne<TChildEntity>(Expression<Func<TEntity, TChildEntity>> navigationPropertyExpression, Action<INavigationOneConfiguration<TEntity, TChildEntity>> navigationOneConfigurationAction)

HasMany

Defines property to navigate to multiple children

IEntityConfiguration<TEntity> HasMany<TChildEntity>(Expression<Func<TEntity, List<TChildEntity>>> navigationPropertyExpression)
IEntityConfiguration<TEntity> HasMany<TChildEntity>(Expression<Func<TEntity, List<TChildEntity>>> navigationPropertyExpression, Action<INavigationManyConfiguration<TEntity, TChildEntity>> navigationManyConfigurationAction)

UseDerivedTypes

When set to true, engine will use force comparison by type if children are inherited and children collection is not abstract

INavigationManyConfiguration<TEntity, TChildEntity> UseDerivedTypes(bool use = false)

OnInsert

Defines operations to perform when an insert is detected

IEntityConfiguration<TEntity> OnInsert(Action<IInsertConfiguration<TEntity>> insertConfigurationAction)

SetValue

When an insert is detected, overwrite a property with a specific value

IInsertConfiguration<TEntity> SetValue<TMember>(Expression<Func<TEntity, TMember>> destinationMember, TMember value)

OnUpdate

Defines operations to perform when an insert is detected. Properties specified in Values(...) will automatically be copied from new entity to existing one

IEntityConfiguration<TEntity> OnUpdate(Action<IUpdateConfiguration<TEntity>> updateConfigurationAction)

SetValue

When an update is detected, overwrite a property with a specific value

IUpdateConfiguration<TEntity> SetValue<TMember>(Expression<Func<TEntity, TMember>> destinationMember, TMember value)

CopyValues

When an update is detected, specify additional properties to copy from new entity to existing one

IUpdateConfiguration<TEntity> CopyValues<TValue>(Expression<Func<TEntity, TValue>> copyValuesExpression)

OnDelete

Defines operations to perform when a delete is detected.

IEntityConfiguration<TEntity> OnDelete(Action<IDeleteConfiguration<TEntity>> deleteConfigurationAction)

SetValue

When a delete is detected, overwrite property with a specific value

IDeleteConfiguration<TEntity> SetValue<TMember>(Expression<Func<TEntity, TMember>> destinationMember, TMember value)

WithComparer

Defines the IEqualityComparer to use when comparing entity of that type

IEntityConfiguration<TEntity> WithComparer<T>(IEqualityComparer<T> equalityComparer)

ForceUpdateIf

Defines additional criteria to force an update even if no update is detected using entity value(s).

IEntityConfiguration<TEntity> ForceUpdateIf(Action<IForceUpdateIfConfiguration<TEntity>> forceUpdateIfConfigurationAction)

NestedEntitiesModified

Trigger an update when a nested entity is modified

IForceUpdateIfConfiguration<TEntity> NestedEntitiesModified()

Equals

Trigger an update when an equality condition is met

IForceUpdateIfConfiguration<TEntity> Equals<TMember>(Expression<Func<TEntity, TMember>> compareToMember, TMember compareToValue)

Ignore

Defines entity properties which will not be found anywhere in the entity diff configuration. This will be used by ValidateIfEveryPropertiesAreReferenced

IEntityConfiguration<TEntity> Ignore<TIgnore>(Expression<Func<TEntity, TIgnore>> ignoreExpression)

NoKey

Defines a no key entity, only update will be deteted for this kind of entity. Mandatory if no HasKey has been defined

IEntityConfiguration<TEntity> NoKey()

Engine configuration

MergeSingle

TEntity MergeSingle<TEntity>(TEntity existingEntity, TEntity newEntity)
TEntity MergeSingle<TEntity>(TEntity existingEntity, TEntity newEntity, IOperationListener operationListener)
TEntity MergeSingle<TEntity>(TEntity existingEntity, TEntity newEntity, Action<IMergeSingleConfiguration> mergeSingleConfigurationAction)
TEntity MergeSingle<TEntity>(TEntity existingEntity, TEntity newEntity, IOperationListener operationListener, Action<IMergeSingleConfiguration> mergeSingleConfigurationAction)

MergeMany

IEnumerable<TEntity> MergeMany<TEntity>(IEnumerable<TEntity> existingEntities, IEnumerable<TEntity> newEntities)
IEnumerable<TEntity> MergeMany<TEntity>(IEnumerable<TEntity> existingEntities, IEnumerable<TEntity> newEntities, IOperationListener operationListener)
IEnumerable<TEntity> MergeMany<TEntity>(IEnumerable<TEntity> existingEntities, IEnumerable<TEntity> newEntities, Action<IMergeManyConfiguration> mergeManyConfigurationAction)
IEnumerable<TEntity> MergeMany<TEntity>(IEnumerable<TEntity> existingEntities, IEnumerable<TEntity> newEntities, IOperationListener operationListener, Action<IMergeManyConfiguration> mergeManyConfigurationAction)

CompareSingle

void CompareSingle<TEntity>(TEntity existingEntity, TEntity newEntity, IOperationListener operationListener);
void CompareSingle<TEntity>(TEntity existingEntity, TEntity newEntity, IOperationListener operationListener, Action<ICompareSingleConfiguration> compareSingleConfigurationAction);

CompareMany

void CompareMany<TEntity>(IEnumerable<TEntity> existingEntities, IEnumerable<TEntity> newEntities, IOperationListener operationListener);
void CompareMany<TEntity>(IEnumerable<TEntity> existingEntities, IEnumerable<TEntity> newEntities, IOperationListener operationListener, Action<ICompareManyConfiguration> compareManyConfigurationAction);

MergeSingle configuration

HashtableThreshold

Defines minimum number of entries in collection to use hashtable (15 by default)

IMergeSingleConfiguration HashtableThreshold(int threshold = 15)

ForceOnUpdateWhenModificationsDetectedOnlyInNestedLevel

Force OnUpdate to be triggered if a nested entity has been modified even if current entity is not modified (false by default))

IMergeSingleConfiguration ForceOnUpdateWhenModificationsDetectedOnlyInNestedLevel(bool force = false)

SetCheckDuplicateKeys

Indicates whether to check for duplicate keys in entities or nested entities (true by default).

IMergeSingleConfiguration SetCheckDuplicateKeys(bool checkDuplicateKeys = true)

MergeMany configuration

HashtableThreshold

Defines minimum number of entries in collection to use hashtable (15 by default)

IMergeManyConfiguration HashtableThreshold(int threshold = 15)

ForceOnUpdateWhenModificationsDetectedOnlyInNestedLevel

Force OnUpdate to be triggered if a nested entity has been modified even if current entity is not modified

IMergeManyConfiguration ForceOnUpdateWhenModificationsDetectedOnlyInNestedLevel(bool force = false)

SetCheckDuplicateKeys

Indicates whether to check for duplicate keys in entities or nested entities (true by default).

IMergeManyConfiguration SetCheckDuplicateKeys(bool checkDuplicateKeys = true)

CompareSingle configuration

HashtableThreshold

Defines minimum number of entries in collection to use hashtable (15 by default)

ICompareSingleConfiguration HashtableThreshold(int threshold = 15);

SetCheckDuplicateKeys

Indicates whether to check for duplicate keys in entities or nested entities (true by default).

ICompareSingleConfiguration SetCheckDuplicateKeys(bool checkDuplicateKeys = true)

CompareMany configuration

HashtableThreshold

Defines minimum number of entries in collection to use hashtable (15 by default)

ICompareManyConfiguration HashtableThreshold(int threshold = 15);

SetCheckDuplicateKeys

Indicates whether to check for duplicate keys in entities or nested entities (true by default).

ICompareManyConfiguration SetCheckDuplicateKeys(bool checkDuplicateKeys = true)

OperationListener

Defines a listener which will be called on every insert/update/delete detection

OnInsert

void OnDelete(string entityTypeName, Func<Dictionary<string, object>> getKeysFunc, Func<Dictionary<string, Dictionary<string, object>>> getNavigationParentKeysFunc);

OnDelete

void OnInsert(string entityTypeName, Func<Dictionary<string, object>> getKeysFunc, Func<Dictionary<string, Dictionary<string, object>>> getNavigationParentKeysFunc);

OnUpdate

void OnUpdate(string entityTypeName, string propertyName, Func<Dictionary<string, object>> getKeysFunc, Func<object> getOriginalValueFunc, Func<Dictionary<string, Dictionary<string, object>>> getNavigationParentKeysFunc);

Deep Diff Configuration

ConfigureEntity

Create an entity configuration

IEntityConfiguration<TEntity> ConfigureEntity<TEntity>()

AddProfile

Add diff profile

IDeepDiffConfiguration AddProfile<TProfile>()
IDeepDiffConfiguration AddProfile(DiffProfile diffProfile)

AddProfiles

Scan assemblies and add diff profile found in those assemblies

IDeepDiffConfiguration AddProfiles(params Assembly[] assembliesToScan)

CreateDeepDiff

Create DeepDiff engine (also validate configuration)

IDeepDiff CreateDeepDiff()

ValidateConfiguration

Validate entity configurations

void ValidateConfiguration()

ValidateIfEveryPropertiesAreReferenced

Check if every properties found in configured entities are used in configuration, use Ignore to add properties to ignore in this validation

void ValidateIfEveryPropertiesAreReferenced()
Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 is compatible.  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 was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net5.0

    • No dependencies.
  • net6.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on DeepDiff:

Package Downloads
DeepDiff.Extensions.Microsoft.DependencyInjection

DeepDeef extensions for Microsft Dependendy Injection

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.12.0 169 11/2/2025
1.11.0 174 9/24/2025
1.10.1 266 5/7/2025
1.10.0 184 4/11/2025
1.9.5 219 4/7/2025
1.9.4 219 4/7/2025
1.9.3 149 4/5/2025
1.9.2 169 4/4/2025
1.9.1 206 3/13/2025
1.9.0 281 3/4/2025
1.8.9 156 2/26/2025
1.8.8 148 2/26/2025
1.8.7 154 2/25/2025
1.8.6 156 2/25/2025
1.8.5 150 1/22/2025
1.8.4 158 1/21/2025
1.8.3 153 1/8/2025
1.8.2 198 7/2/2024
1.8.1 180 6/27/2024
1.8.0 170 6/21/2024
1.7.0 199 4/30/2024
1.6.4 183 4/26/2024
1.6.3 193 3/15/2024
1.6.2 174 2/27/2024
1.6.1 183 2/26/2024
1.6.0 169 2/22/2024
1.5.1 206 2/14/2024
1.5.0 557 1/31/2024
1.4.2 152 1/30/2024
1.4.1 165 1/30/2024
1.4.0 173 1/29/2024
1.3.6 178 1/27/2024
1.3.5 168 1/26/2024
1.3.4 163 1/26/2024
1.3.3 212 1/26/2024
1.3.2 163 1/25/2024
1.3.1 174 1/24/2024
1.3.0 166 1/24/2024
1.2.3 173 1/18/2024
1.2.2 186 1/9/2024
1.2.1 218 12/15/2023
1.1.1 183 12/7/2023
1.1.0 254 12/4/2023
1.0.2 241 12/2/2023
1.0.1 239 12/1/2023
1.0.0 182 12/1/2023