Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public static void UpdateCollection<TEntity, TChild>(this DbContext context, TEntity parent, Expression<Func<TEntity, IEnumerable<TChild>>> expression, IEnumerable<TChild> current)
- where TEntity : class
- where TChild : class
- {
- var collection = expression.Compile()(parent);
- var baseType = GetBaseType<TChild>();
- var properties = GetEntityKeyNamesInternal(context, baseType).Select(pn => baseType.GetProperty(pn));
- foreach (var item in collection)
- {
- var ids = GetEntityKeyValuesInternal(item, properties);
- var entry = context.Entry(item);
- if (IsNotDefault(ids))
- {
- var isInCurrent = current.Any(cur => GetEntityKeyValues(context, cur).SequenceEqual(ids));
- entry.State = isInCurrent ? EntityState.Modified : EntityState.Deleted;
- }
- else
- {
- entry.State = EntityState.Added;
- }
- }
- }
- /// <summary>
- ///
- /// </summary>
- /// <typeparam name="TEntity"></typeparam>
- /// <typeparam name="TElement"></typeparam>
- /// <param name="context"></param>
- /// <param name="parent"></param>
- /// <param name="navigationProperty"></param>
- /// <param name="loadReference">indicates whether to load the related reference, or it has already been pre-loaded before.</param>
- /// <returns></returns>
- public static async Task UpdateCollectionAsync<TEntity, TElement>(this DbContext context, TEntity parent, Expression<Func<TEntity, ICollection<TElement>>> navigationProperty, bool loadReference = true)
- where TEntity : class
- where TElement : class
- {
- //check if key value equals to default value (i.e. Id == 0)
- Func<TElement, bool> notDefaultKeyValuePredicate =
- (e) => //context.GetEntityKeyValues(e).Any(ek => object.Equals(Activator.CreateInstance(ek.GetType()), ek));
- IsNotDefault(context.GetEntityKeyValues(e));
- var collectionExtractor = navigationProperty.Compile();
- var newCollection = collectionExtractor(parent).ToArray();
- var newlyAdded = newCollection.Where(e => !notDefaultKeyValuePredicate(e));
- foreach (var newItem in newlyAdded)
- context.Entry(newItem).State = EntityState.Added;
- //context.Set<TEntity>().Attach(parent);
- var entityEntry = context.Entry(parent);
- //entityEntry.State = EntityState.Modified;
- if (loadReference)
- await entityEntry.Collection(navigationProperty).LoadAsync();
- var existingCollection = collectionExtractor(parent).ToArray();
- var existing = existingCollection.Intersect(newCollection);
- //select only store items
- foreach (var item in existingCollection.Where(notDefaultKeyValuePredicate))
- {
- var intersected = newCollection.SingleOrDefault(nI =>
- {
- var curKeys = context.GetEntityKeyValues(nI);
- return curKeys.SequenceEqual(context.GetEntityKeyValues(item));
- });
- var isIntersected = intersected != null;
- context.Entry(item).State =
- isIntersected
- ? EntityState.Modified
- : EntityState.Deleted;
- }
- }
- public static void UpdateNavigation<TEntity, TNavigation>(this DbContext context, TEntity parent, Expression<Func<TEntity, TNavigation>> navigationProperty, params Expression<Func<TEntity, object>>[] storeEntityIdsExpressions)
- where TEntity : class
- where TNavigation : class
- {
- var entityBaseType = GetBaseType<TEntity>();
- var set = context.Set(entityBaseType);
- var currentEntity = navigationProperty.Compile()(parent);
- if (currentEntity != null)
- {
- var currentIds = context.GetEntityKeyValues(currentEntity);
- var isCurrentStored = IsNotDefault(currentIds);
- if (isCurrentStored)
- {
- set.Attach(currentEntity);
- context.SetState(currentEntity, EntityState.Modified);
- return; //no need to delete existing as its refers to the same as this one.
- }
- else
- {
- //make sure it's in added state
- }
- }
- //else //currentEntity == null
- //goto deleteStoreEntity;
- //deleteStoreEntity:
- if (storeEntityIdsExpressions != null)
- {
- var attachment = Activator.CreateInstance<TEntity>();
- var ids = new object[storeEntityIdsExpressions.Length];
- for (int i = 0; i < storeEntityIdsExpressions.Length; i++)
- {
- var expression = storeEntityIdsExpressions[i];
- ids[i] = expression.Compile()(parent);
- var uExp = expression.Body as UnaryExpression;
- var member = (MemberExpression)(uExp != null ? uExp.Operand : uExp);
- var property = (PropertyInfo)member.Member;
- var propType = property.PropertyType;
- property.SetValue(parent, propType.IsValueType ? Activator.CreateInstance(propType) : null);
- }
- if (IsNotDefault(ids))
- {
- context.SetState(parent, EntityState.Modified);
- context.SetEntityKeyValues(attachment, ids);
- set.Attach(attachment);
- context.SetState(attachment, EntityState.Deleted);
- }
- }
- }
- private static bool IsNotDefault(IEnumerable<object> entityIds)
- {
- return entityIds != null
- && entityIds.All(id =>
- (id is string && ((string)id).Any())
- || (id is IConvertible && ((IConvertible)id).ToInt64(null) > 0));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement