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); }
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; } } }