private void ProcessAutogeneratedKeys() { var tempKeys = EntitiesWithAutoGeneratedKeys.Cast <EFEntityInfo>().Where( entityInfo => entityInfo.AutoGeneratedKey.AutoGeneratedKeyType == AutoGeneratedKeyType.KeyGenerator) .Select(ei => new TempKeyInfo(ei)) .ToList(); if (tempKeys.Count == 0) { return; } if (this.KeyGenerator == null) { this.KeyGenerator = GetKeyGenerator(); } this.KeyGenerator.UpdateKeys(tempKeys); tempKeys.ForEach(tki => { // Clever hack - next 3 lines cause all entities related to tki.Entity to have // their relationships updated. So all related entities for each tki are updated. // Basically we set the entity to look like a preexisting entity by setting its // entityState to unchanged. This is what fixes up the relations, then we set it back to added // Now when we update the pk - all fks will get changed as well. Note that the fk change will only // occur during the save. var entry = GetObjectStateEntry(tki.Entity); entry.ChangeState(System.Data.EntityState.Unchanged); entry.ChangeState(System.Data.EntityState.Added); var val = ConvertValue(tki.RealValue, tki.Property.PropertyType); tki.Property.SetValue(tki.Entity, val, null); }); }
private List <KeyMapping> UpdateAutoGeneratedKeys() { // where clause is necessary in case the Entities were suppressed in the beforeSave event. var keyMappings = EntitiesWithAutoGeneratedKeys.Cast <EFEntityInfo>() .Where(entityInfo => entityInfo.ObjectStateEntry != null) .Select(entityInfo => { var autoGeneratedKey = entityInfo.AutoGeneratedKey; if (autoGeneratedKey.AutoGeneratedKeyType == AutoGeneratedKeyType.Identity) { autoGeneratedKey.RealValue = GetOsePropertyValue(entityInfo.ObjectStateEntry, autoGeneratedKey.PropertyName); } return(new KeyMapping() { EntityTypeName = entityInfo.Entity.GetType().FullName, TempValue = autoGeneratedKey.TempValue, RealValue = autoGeneratedKey.RealValue }); }); return(keyMappings.ToList()); }
protected override List <KeyMapping> SaveChangesCore(Dictionary <Type, List <EntityInfo> > saveMap) { var deletedEntities = ProcessSaves(saveMap); if (deletedEntities.Any()) { ProcessAllDeleted(deletedEntities); } ProcessAutogeneratedKeys(); int count; try { if (Context is DbContext) { count = ((DbContext)(object)Context).SaveChanges(); } else { count = ObjectContext.SaveChanges(System.Data.Objects.SaveOptions.AcceptAllChangesAfterSave); } } catch (DbEntityValidationException e) { var msg = ""; foreach (var eve in e.EntityValidationErrors) { var entity = eve.Entry.Entity; var key = ObjectContext.ObjectStateManager.GetObjectStateEntry(entity).EntityKey; if (key.EntityKeyValues != null) { var formattedKey = key.EntitySetName + ";" + key.EntityKeyValues.Select(v => v.ToString()).ToAggregateString(" ,"); msg += String.Format("\n'{0}' has the following validation errors:", formattedKey); } else { var entityInfo = EntitiesWithAutoGeneratedKeys.FirstOrDefault(ei => ei.Entity == entity); if (entityInfo != null) { var formattedKey = key.EntitySetName + ";(Temporary Key);" + entityInfo.AutoGeneratedKey.TempValue; msg += String.Format("\n'{0}' has the following validation errors:", formattedKey); } else { msg += "Validation error:"; } } foreach (var ve in eve.ValidationErrors) { if (ve.PropertyName != null) { msg += String.Format("\n Property: '{0}', Error: '{1}'", ve.PropertyName, ve.ErrorMessage); } else { msg += String.Format("\n Error: '{0}'", ve.ErrorMessage); } } } throw new ValidationException(msg); } catch (Exception e2) { throw; } return(UpdateAutoGeneratedKeys()); }