Skip to content

Instantly share code, notes, and snippets.

@jasoncable
Created November 20, 2019 17:40
Show Gist options
  • Save jasoncable/cadc8c81717a66bd7fed580b86bb9722 to your computer and use it in GitHub Desktop.
Save jasoncable/cadc8c81717a66bd7fed580b86bb9722 to your computer and use it in GitHub Desktop.
C# - DTO to Entity Comparison that outputs items to add/delete/update to/from/in target collection
// Let's say you have a list of DTOs (data tranfer objects) that someone
// posted on the web or anywhere. Items have been removed and added to it.
// You need to compare the input with what exists in the database
// and find out 1.) new items to add to the database,
// 2.) items to delete from the database, and
// 3.) items to update in the database.
// You don't want to continually rewrite that sort of thing over and over again, like I have.
// The problem with conventional methods is that the data types on either side of the
// equation are probably different types.
// The following will produce the items to add/delete/update by comparing them via
// a user-defined comparison Func<T,U,bool>.
//
// This sample assumes a list of ThingDto objects that are posted from the web
// and using EntityFramework, we compare what is in the database versus what
// is coming in from the web.
DbContext context = new DbContext(); // pretend EntityFramework // context.Things is of type ThingEntity
List<ThingDto> listPostedFromWeb;// passed in parameter
Func<ThingDto, ThingEntity, bool> comparer = (compDto, compEntity) =>
{
// what comparison between these different types ensures
// that they are the same?
return compDto.Id == compEntity.id;
};
var (insert, update, delete) = GetChanges(
listPostedFromWeb ?? new List<ThingDto>(), // list from the web or a new list
context.Things.Where(x => x.CategoryId == XYZ), // EntityFramework query
comparer); // your custom comparer.
public (IEnumerable<L> insert, IEnumerable<R> update, IEnumerable<R> delete) GetChanges<L,R>(IEnumerable<L> models, IEnumerable<R> dos, Func<L,R,bool> comparer)
{
IEnumerable<L> itemsToInsert;
if (models == null)
itemsToInsert = new List<L>();
else if (dos == null)
itemsToInsert = models;
else
itemsToInsert = models.Where(x => !dos.Any(y => comparer(x, y))).ToList();
IEnumerable<R> itemsToUpdate;
if (models == null || dos == null)
itemsToUpdate = new List<R>();
else
itemsToUpdate = dos.Where(x => models.Any(y => comparer(y, x))).ToList();
IEnumerable<R> itemsToDelete;
if (models == null)
itemsToDelete = dos;
else if (dos == null)
itemsToDelete = new List<R>();
else
itemsToDelete = dos.Where(x => !models.Any(y => comparer(y, x))).ToList();
return (itemsToInsert, itemsToUpdate, itemsToDelete);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment