public static IReadOnlyList <T> UpdateManyToMany <T, TParent, TChild, TChildDto>(this IFolkeConnection connection, TParent parent, IReadOnlyList <T> currentValues, ICollection <TChildDto> newDtos, IManyToManyHelperConfiguration <TChild, TChildDto> helper) where T : class, IManyToManyTable <TParent, TChild>, new() where TParent : IFolkeTable where TChild : class, IFolkeTable, new() { if (newDtos == null) { newDtos = new List <TChildDto>(); } // Looking for any value in newDtos that is not in currentValues var valuesToAdd = newDtos.Where(v => currentValues == null || !currentValues.Any(cv => helper.AreEqual(cv.Child, v))).ToList(); var newValues = currentValues?.ToList() ?? new List <T>(); if (valuesToAdd.Any()) { // Query from the database the values that needs to be added to the parent var existingChildren = helper.QueryExisting(connection, valuesToAdd); foreach (var newDto in valuesToAdd) { var child = existingChildren?.SingleOrDefault(c => helper.AreEqual(c, newDto)); if (child == null) { // If the element to add does not exist in the database, create it (may fail if helper.Map/helper.UpdateDto is not implemented because one does not want to allow that) child = helper.Map(newDto); connection.Save(child); helper.UpdateDto(newDto, child); } // Create a new parent-child link with this value var newElement = new T { Child = child, Parent = parent }; connection.Save(newElement); newValues.Add(newElement); } } if (currentValues != null) { // Look for values to remove var valuesToRemove = currentValues.Where(cv => newDtos.All(nv => !helper.AreEqual(cv.Child, nv))).ToArray(); if (valuesToRemove.Any()) { connection.Delete <T>().From().Where(c => c.Id.In(valuesToRemove.Select(s => s.Id))).Execute(); foreach (var value in valuesToRemove) { newValues.Remove(value); } } } return(newValues); }
public void Delete(int id) { Product product = session.Get <Product>(id); if (product == null) { return; } session.Delete <Product>(product); return; }
/// <summary> /// Updates a collection of items from a collection of item views. Existing items are updated or deleted. New items are added. /// </summary> /// <typeparam name="TChild">The database item</typeparam> /// <typeparam name="TChildView">A view of this database item. Matching items have same Id</typeparam> /// <param name="connection">The database connection</param> /// <param name="currentValues">The current value from the database</param> /// <param name="newValues">The new values</param> /// <param name="factory">A factory that create a new item</param> /// <param name="updater">A delegate that updates an existing item</param> public static List <TChild> UpdateCollectionFromViews <TChild, TChildView>(this IFolkeConnection connection, IReadOnlyCollection <TChild> currentValues, IReadOnlyCollection <TChildView> newValues, Func <TChildView, TChild> factory, Func <TChildView, TChild, bool> updater) where TChild : class, IFolkeTable, new() where TChildView : class, IFolkeTable, new() { var ret = new List <TChild>(); if (currentValues == null || !currentValues.Any()) { foreach (var childValue in newValues) { var child = factory(childValue); ret.Add(child); connection.Save(child); } return(ret); } var newValueToAdd = newValues.Where(x => currentValues.All(y => y.Id != x.Id)); foreach (var currentValue in currentValues) { var newValue = newValues.FirstOrDefault(x => x.Id == currentValue.Id); if (newValue == null) { connection.Delete(currentValue); } else { if (updater != null && updater(newValue, currentValue)) { connection.Update(currentValue); } ret.Add(currentValue); } } foreach (var childDto in newValueToAdd) { var child = factory(childDto); ret.Add(child); connection.Save(child); } return(ret); }
/// <summary> /// Update a collection of items using a collection of values. These values don't have an id to identity them, so a areEqual delegate /// must be given as a parameter. Existing items that is not in newValues are deleted. /// </summary> /// <typeparam name="TChild">The database item type</typeparam> /// <typeparam name="TChildView">The view type</typeparam> /// <param name="connection">The database connection</param> /// <param name="currentValues">The current value from the database</param> /// <param name="newValues">The new values</param> /// <param name="areEqual">Must return true if the two values are equal</param> /// <param name="factory">Create a new item</param> public static List <TChild> UpdateCollectionFromValues <TChild, TChildView>(this IFolkeConnection connection, IReadOnlyCollection <TChild> currentValues, IReadOnlyCollection <TChildView> newValues, Func <TChildView, TChild> factory, Func <TChildView, TChild, bool> areEqual) where TChild : class, IFolkeTable, new() { var ret = new List <TChild>(); if (currentValues == null || !currentValues.Any()) { foreach (var childValue in newValues) { var child = factory(childValue); connection.Save(child); ret.Add(child); } return(ret); } var newValueToAdd = newValues.Where(x => currentValues.All(y => !areEqual(x, y))); foreach (var currentValue in currentValues) { if (!newValues.Any(x => areEqual(x, currentValue))) { connection.Delete(currentValue); } else { ret.Add(currentValue); } } foreach (var childDto in newValueToAdd) { var child = factory(childDto); connection.Save(child); ret.Add(child); } return(ret); }