예제 #1
0
        /// <summary>
        /// Adds or updates entities by key when SaveChanges is called. Equivalent to an "upsert" operation
        /// from database terminology.
        /// This method can useful when seeding data using Migrations.
        /// </summary>
        /// <typeparam name="TEntity">The type of entities to add or update.</typeparam>
        /// <param name="set">The set to which the entities belong.</param>
        /// <param name="entities"> The entities to add or update. </param>
        /// <remarks>
        /// When the <paramref name="set" /> parameter is a custom or fake IDbSet implementation, this method will
        /// attempt to locate and invoke a public, instance method with the same signature as this extension method.
        /// </remarks>
        public static void AddOrUpdate <TEntity>(this IDbSet <TEntity> set, params TEntity[] entities) where TEntity : class
        {
            Check.NotNull <IDbSet <TEntity> >(set, nameof(set));
            Check.NotNull <TEntity[]>(entities, nameof(entities));
            DbSet <TEntity> set1 = set as DbSet <TEntity>;

            if (set1 != null)
            {
                InternalSet <TEntity> internalSet = (InternalSet <TEntity>)((IInternalSetAdapter)set1).InternalSet;
                if (internalSet != null)
                {
                    set1.AddOrUpdate <TEntity>(DbSetMigrationsExtensions.GetKeyProperties <TEntity>(typeof(TEntity), internalSet), internalSet, entities);
                    return;
                }
            }
            Type       type           = set.GetType();
            MethodInfo declaredMethod = type.GetDeclaredMethod(nameof(AddOrUpdate), typeof(TEntity[]));

            if (declaredMethod == (MethodInfo)null)
            {
                throw Error.UnableToDispatchAddOrUpdate((object)type);
            }
            declaredMethod.Invoke((object)set, (object[])new TEntity[1][]
            {
                entities
            });
        }
예제 #2
0
        private static void AddOrUpdate <TEntity>(
            this DbSet <TEntity> set,
            IEnumerable <PropertyPath> identifyingProperties,
            InternalSet <TEntity> internalSet,
            params TEntity[] entities)
            where TEntity : class
        {
            IEnumerable <PropertyPath> keyProperties = DbSetMigrationsExtensions.GetKeyProperties <TEntity>(typeof(TEntity), internalSet);
            ParameterExpression        parameter     = Expression.Parameter(typeof(TEntity));

            foreach (TEntity entity1 in entities)
            {
                TEntity    entity = entity1;
                Expression body   = identifyingProperties.Select <PropertyPath, BinaryExpression>((Func <PropertyPath, BinaryExpression>)(pi => Expression.Equal((Expression)Expression.Property((Expression)parameter, pi.Single <PropertyInfo>()), (Expression)Expression.Constant(pi.Last <PropertyInfo>().GetValue((object)entity, (object[])null))))).Aggregate <BinaryExpression, Expression>((Expression)null, (Func <Expression, BinaryExpression, Expression>)((current, predicate) =>
                {
                    if (current != null)
                    {
                        return((Expression)Expression.AndAlso(current, (Expression)predicate));
                    }
                    return((Expression)predicate);
                }));
                TEntity entity2 = set.SingleOrDefault <TEntity>(Expression.Lambda <Func <TEntity, bool> >(body, parameter));
                if ((object)entity2 != null)
                {
                    foreach (PropertyPath source in keyProperties)
                    {
                        source.Single <PropertyInfo>().GetPropertyInfoForSet().SetValue((object)(TEntity)entity, source.Single <PropertyInfo>().GetValue((object)entity2, (object[])null), (object[])null);
                    }
                    internalSet.InternalContext.Owner.Entry <TEntity>(entity2).CurrentValues.SetValues((object)(TEntity)entity);
                }
                else
                {
                    internalSet.Add((object)(TEntity)entity);
                }
            }
        }