/// <summary> /// Creates new <see cref="Structure"/> of the specified type filled with provided data. /// </summary> /// <param name="structureType">The type of structure to create. Must be descendant of the <see cref="Structure"/> type.</param> /// <param name="structureData">The structure data tuple.</param> /// <returns>Created structure.</returns> public Structure CreateStructure(Type structureType, Tuple structureData) { using (Session.OpenSystemLogicOnlyRegion()) { ArgumentValidator.EnsureArgumentNotNull(structureType, "structureType"); if (!WellKnownOrmTypes.Structure.IsAssignableFrom(structureType)) { throw new InvalidOperationException( string.Format(Strings.TypeXIsNotAnYDescendant, structureType, WellKnownOrmTypes.Structure)); } return(Activator.CreateStructure(Session, structureType, structureData)); } }
internal void SetFieldValue(FieldInfo field, object value, SyncContext syncContext, RemovalContext removalContext) { if (field.ReflectedType.IsInterface) { field = TypeInfo.FieldMap[field]; } SystemSetValueAttempt(field, value); var fieldAccessor = GetFieldAccessor(field); object oldValue = GetFieldValue(field); // Handling 'OldValue != NewValue' problem for structures var o = oldValue as Structure; if (o != null) { oldValue = Activator.CreateStructure(Session, o.GetType(), o.Tuple.ToRegular()); } try { var operations = Session.Operations; var scope = operations.BeginRegistration(Operations.OperationType.System); try { var entity = this as Entity; if (entity != null) { if (operations.CanRegisterOperation) { operations.RegisterOperation(new EntityFieldSetOperation(entity.Key, field, value)); } var entityValue = value as IEntity; if (entityValue != null) { var valueKey = entityValue.Key; Session.ReferenceFieldsChangesRegistry.Register(entity.Key, valueKey, field); } } else { var persistent = this; var currentField = field; var structure = persistent as Structure; while (structure != null && structure.Owner != null) { var pair = new Pair <FieldInfo>(structure.Field, currentField); currentField = structure.Owner.TypeInfo.StructureFieldMapping[pair]; persistent = structure.Owner; structure = persistent as Structure; } entity = persistent as Entity; if (entity != null) { if (operations.CanRegisterOperation) { operations.RegisterOperation(new EntityFieldSetOperation(entity.Key, currentField, value)); } var entityValue = value as IEntity; if (entityValue != null) { var valueKey = entityValue.Key; Session.ReferenceFieldsChangesRegistry.Register(entity.Key, valueKey, field); } } } if (fieldAccessor.AreSameValues(oldValue, value)) { operations.NotifyOperationStarting(false); scope.Complete(); return; } { SystemBeforeSetValue(field, value); operations.NotifyOperationStarting(false); AssociationInfo association = null; entity = value as Entity ?? oldValue as Entity; if (entity != null) { association = field.GetAssociation(entity.TypeInfo); } if (association != null && association.IsPaired) { Key currentKey = GetReferenceKey(field); Key newKey = null; var newReference = (Entity)(object)value; if (newReference != null) { newKey = newReference.Key; } if (currentKey != newKey) { Session.PairSyncManager.ProcessRecursively(syncContext, removalContext, OperationType.Set, association, (Entity)this, newReference, () => { SystemBeforeTupleChange(); fieldAccessor.SetUntypedValue(this, value); SystemTupleChange(); }); } } else { // The method of Equals(object, object) wrapped with in a block 'try catch', // because that for data types NpgsqlPath and NpgsqlPolygon which are defined without an initial value it works incorrectly. bool canBeEqual; try { canBeEqual = Equals(value, oldValue); } catch (Exception) { canBeEqual = false; } if (!canBeEqual || field.IsStructure) { SystemBeforeTupleChange(); value = AdjustFieldValue(field, oldValue, value); fieldAccessor.SetUntypedValue(this, value); SystemTupleChange(); } } if (removalContext != null) { // Postponing finalizers (events) removalContext.EnqueueFinalizer(() => { try { try { SystemSetValue(field, oldValue, value); SystemSetValueCompleted(field, oldValue, value, null); scope.Complete(); } finally { scope.DisposeSafely(); } } catch (Exception e) { SystemSetValueCompleted(field, oldValue, value, e); throw; } }); return; } SystemSetValue(field, oldValue, value); SystemSetValueCompleted(field, oldValue, value, null); } scope.Complete(); } finally { if (removalContext == null) { scope.DisposeSafely(); } } } catch (Exception e) { SystemSetValueCompleted(field, oldValue, value, e); throw; } }