private static async Task PrepareEntry <TEntity>(
            SubmitContext context, DbContext dbContext, DataModificationEntry entry, DbSet <TEntity> set, CancellationToken cancellationToken)
            where TEntity : class
        {
            Type    entityType = typeof(TEntity);
            TEntity entity;

            if (entry.IsNew)
            {
                // TODO: See if Create method is in DbSet<> in future EF7 releases, as the one EF6 has.
                entity = (TEntity)Activator.CreateInstance(typeof(TEntity));

                ChangeSetPreparer.SetValues(entity, entityType, entry.LocalValues);
                set.Add(entity);
            }
            else if (entry.IsDelete)
            {
                entity = (TEntity)await ChangeSetPreparer.FindEntity(context, entry, cancellationToken);

                set.Remove(entity);
            }
            else if (entry.IsUpdate)
            {
                entity = (TEntity)await ChangeSetPreparer.FindEntity(context, entry, cancellationToken);

                var dbEntry = dbContext.Update(entity);
                ChangeSetPreparer.SetValues(dbEntry, entry, entityType);
            }
            else
            {
                throw new NotSupportedException(Resources.DataModificationMustBeCUD);
            }

            entry.Entity = entity;
        }
        private static object CreateFullUpdateInstance(DataModificationEntry entry, Type entityType)
        {
            // The algorithm for a "FullReplaceUpdate" is taken from ObjectContextServiceProvider.ResetResource
            // in WCF DS, and works as follows:
            //  - Create a new, blank instance of the entity.
            //  - Copy over the key values and set any updated values from the client on the new instance.
            //  - Then apply all the properties of the new instance to the instance to be updated.
            //    This will set any unspecified properties to their default value.
            object newInstance = Activator.CreateInstance(entityType);

            ChangeSetPreparer.SetValues(newInstance, entityType, entry.EntityKey);
            ChangeSetPreparer.SetValues(newInstance, entityType, entry.LocalValues);

            return(newInstance);
        }
Exemple #3
0
 static ChangeSetPreparer()
 {
     Instance = new ChangeSetPreparer();
 }
 static ChangeSetPreparer()
 {
     Instance = new ChangeSetPreparer();
 }
        private static void SetValues(EntityEntry dbEntry, DataModificationEntry entry, Type entityType)
        {
            //StateEntry stateEntry = ((IAccessor<InternalEntityEntry>) dbEntry.StateEntry;
            IEntityType edmType = dbEntry.Metadata;

            if (entry.IsFullReplaceUpdate)
            {
                // The algorithm for a "FullReplaceUpdate" is taken from WCF DS ObjectContextServiceProvider.ResetResource, and is as follows:
                // Create a new, blank instance of the entity.  Copy over the key values, and set any updated values from the client on the new instance.
                // Then apply all the properties of the new instance to the instance to be updated.  This will set any unspecified
                // properties to their default value.

                object newInstance = Activator.CreateInstance(entityType);

                ChangeSetPreparer.SetValues(newInstance, entityType, entry.EntityKey);
                ChangeSetPreparer.SetValues(newInstance, entityType, entry.LocalValues);

                foreach (var property in edmType.GetProperties())
                {
                    object val;
                    if (!entry.LocalValues.TryGetValue(property.Name, out val))
                    {
                        PropertyInfo propertyInfo = entityType.GetProperty(property.Name);
                        val = propertyInfo.GetValue(newInstance);
                    }
                    //stateEntry[property] = val;
                    dbEntry.Property(property.Name).CurrentValue = val;
                }
            }
            else
            {
                // For some properties like DateTimeOffset, the backing EF property could be of a different type like DateTime, so we can't just
                // copy every property pair in DataModificationEntry to EF StateEntry, instead we let the entity type to do the conversion, by
                // first setting the EDM property (in DataModificationEntry) to a entity instance, then getting the EF mapped property from the
                // entity instance and set to StateEntry.

                object instance = null;

                foreach (var property in edmType.GetProperties())
                {
                    object val;

                    var edmPropName = (string)property["EdmPropertyName"];
                    if (edmPropName != null && entry.LocalValues.TryGetValue(edmPropName, out val))
                    {
                        if (instance == null)
                        {
                            instance = Activator.CreateInstance(entityType);
                        }
                        PropertyInfo edmPropInfo = entityType.GetProperty(edmPropName);
                        edmPropInfo.SetValue(instance, val);

                        PropertyInfo propertyInfo = entityType.GetProperty(property.Name);
                        val = propertyInfo.GetValue(instance);
                    }
                    else if (!entry.LocalValues.TryGetValue(property.Name, out val))
                    {
                        continue;
                    }
                    //stateEntry[property] = val;
                    dbEntry.Property(property.Name).CurrentValue = val;
                }
            }
        }