Skip to content

Instantly share code, notes, and snippets.

@michaellperry
Last active February 7, 2017 03:56
Show Gist options
  • Save michaellperry/5fe67b8a447c1465c3867f738196f47b to your computer and use it in GitHub Desktop.
Save michaellperry/5fe67b8a447c1465c3867f738196f47b to your computer and use it in GitHub Desktop.
public static class DbSetExtensions
{
public static void AddOrUpdateFaster<TEntity>(
this DbSet<TEntity> set,
Expression<Func<TEntity, int>> identifierExpression,
IEqualityComparer<TEntity> entityComparer,
params TEntity[] entities)
where TEntity : class
{
var identifierFunction = identifierExpression.Compile();
var currentValues = set.OrderBy(identifierExpression).ToArray();
var desiredValues = entities.OrderBy(identifierFunction).ToArray();
if (!currentValues.Any())
{
set.AddRange(desiredValues);
}
else if (!currentValues.SequenceEqual(desiredValues, entityComparer))
{
var pairs = desiredValues.GroupJoin(currentValues,
identifierFunction, identifierFunction,
(desired, group) => new { desired, current = group.SingleOrDefault() });
foreach (var pair in pairs)
{
if (pair.current != null)
{
foreach (var property in typeof(TEntity).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
property.SetValue(pair.current, property.GetValue(pair.desired));
}
}
else
{
set.Add(pair.desired);
}
}
}
}
}
@michaellperry
Copy link
Author

michaellperry commented Feb 6, 2017

Note, this only works for integer identifiers. A similar function could be written for other data types.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment