예제 #1
0
		/// <summary>
		/// Builds and returns a new record using the schema and values stored in this builder.
		/// </summary>
		/// <param name="autoDispose">True to dispose this builder as soon as the new record is generated.</param>
		/// <returns>A new record built using the schema and values stored in this builder.</returns>
		public KRecord Generate( bool autoDispose = true )
		{
			if( _Schema == null ) throw new InvalidOperationException( "Builder Schema is null." );
			if( _Schema.Count < 0 ) throw new InvalidOperationException( "Builder Schema is disposed." );
			if( _Schema.Count == 0 ) throw new InvalidOperationException( "Builder Schema is empty." );

			KRecord record = new KRecord( _Schema );
			for( int i = 0; i < _Values.Count; i++ ) record[i] = _Values[i];

			if( autoDispose ) Dispose();
			return record;
		}
예제 #2
0
		protected virtual void Dispose( bool disposing )
		{
			_Record = null;
			_Table = null;
		}
예제 #3
0
		internal KRecordDynamicTable( KRecord record, string table )
		{
			_Record = record;
			_Table = table.Validated( "Table Name" );
		}
예제 #4
0
		/// <summary>
		/// Returns whether this record can be considered equivalent to the other record.
		/// <para>Strict mode can be requested, in which case all columns in both records are taken in consideration.</para>
		/// <para>When not in strict mode, only the columns of the source record are compared.</para>
		/// </summary>
		/// <param name="other">The other record to use in the comparison.</param>
		/// <param name="strict">True to activate strict mode, false otherwise.</param>
		/// <returns>Whether this record can be considered equivalent to the other record.</returns>
		public bool EquivalentTo( KRecord other, bool strict = true )
		{
			KRecord changes = Changes( other, strict );
			bool r = changes == null ? true : false;

			if( changes != null ) { changes.Schema.Dispose(); changes.Dispose(); }
			return r;
		}
예제 #5
0
		/// <summary>
		/// Returns a new ad-hoc record containing the changes from this record compared against the other record given.
		/// <para>Strict mode can be requeste, in which case all columns in both records are taken in consideration.</para>
		/// <para>When not in strict mode, only the columns of the source record are compared.</para>
		/// </summary>
		/// <param name="other">The other record to use in the comparison.</param>
		/// <param name="strict">True to activate strict mode, false otherwise.</param>
		/// <returns>A new record containing the changes and its schema, or null if no changes were detected.</returns>
		public KRecord Changes( KRecord other, bool strict = false )
		{
			if( this._Schema == null ) throw new InvalidOperationException( "This record's schema is null." );
			if( this.Schema.Count < 0 ) throw new InvalidOperationException( "This record's schema is disposed." );

			if( other == null ) throw new ArgumentNullException( "other", "Other record cannot be null." );
			if( other.Schema == null ) throw new InvalidOperationException( "Other record's schema is null." );
			if( other.Schema.Count < 0 ) throw new InvalidOperationException( "Other record's schema is disposed." );

			// If any record is empty...
			if( this.Schema.Count == 0 ) {
				if( other.Schema.Count == 0 ) return null; // Both are empty records...
				if( !strict ) return null; // We have no changes to inform about...
				return other.Clone( cloneSchema: true ); // All other contents are consideres as changed...
			}
			if( other.Schema.Count == 0 ) {
				if( !strict ) return null; // We have no changes to inform about...
				return this.Clone( cloneSchema: true ); // All other contents are consideres as changed...
			}

			// Preparing for returning a new record containing the changes...
			KSchema schema = new KSchema( _Schema.CaseSensitiveNames );
			List<object> values = new List<object>();
			bool anyTable = strict ? false : true;

			// First round: using this record's columns...
			for( int thisIx = 0; thisIx < this.Schema.Count; thisIx++ ) {
				var thisMeta = this.Schema[thisIx];
				var otherMeta = other.Schema.Find( thisMeta.BaseTableName, thisMeta.ColumnName, anyTable, raise: false );

				if( otherMeta == null ) { // Columns not found in other are considered only in strict mode...
					if( strict ) {
						object thisValue = this[thisIx];
						schema.Add( thisMeta.Clone() );
						values.Add( TypeHelper.TryClone( thisValue ) );
					}
				}
				else { // Only annotating when their contents are not equivalent...
					int otherIx = other.Schema.IndexOf( otherMeta );
					object thisValue = this[thisIx];
					object otherValue = other[otherIx];
					bool eq = TypeHelper.AreEquivalent( thisValue, otherValue ); if( !eq ) {
						schema.Add( thisMeta.Clone() );
						values.Add( TypeHelper.TryClone( thisValue ) );
					}
				}
			}

			// Second round: in strict we need to consider also the columns in other that do not appear in this...
			if( strict ) {
				for( int otherIx = 0; otherIx < other.Schema.Count; otherIx++ ) {
					var otherMeta = other.Schema[otherIx];
					var thisMeta = this.Schema.Find( otherMeta.BaseTableName, otherMeta.ColumnName, anyTable: false, raise: false );

					if( thisMeta == null ) { // Adding from a new column in the other record...
						var temp = schema.Find( otherMeta.BaseTableName, otherMeta.ColumnName, anyTable: true, raise: false );
						
						if( temp == null ) { // Avoiding exception per duplicate columns...
							object otherValue = other[otherIx];
							schema.Add( otherMeta.Clone() );
							values.Add( TypeHelper.TryClone( otherValue ) );
						}
					}
				}
			}

			// If no changes return null to facilitate comparisons...
			if( schema.Count == 0 ) { values = null; schema.Dispose(); schema = null; return null; }

			// Otherwise, generating the actual record containing the changes...
			KRecord record = new KRecord();
			record._Schema = schema;
			record._Columns = values.ToArray();
			return record;
		}
예제 #6
0
		/// <summary>
		/// Returns a new clone of this record, optionally cloning the schema it was associated to.
		/// <para>If cloning the schema was not requested, then the new clone will be associated whith the original schema
		/// instance. Otherwise, it will be associated with a clone of the original schema.</para>
		/// <para>It also tries to clone the contents of the original record, if possible.</para>
		/// </summary>
		/// <param name="cloneSchema">True to also clone the schema.</param>
		/// <returns>The newly created clone.</returns>
		public KRecord Clone( bool cloneSchema )
		{
			KRecord cloned = new KRecord();

			if( _Schema == null ) throw new InvalidOperationException( "Cannot clone from a record with a null schema." );
			if( _Schema.Count == 0 ) throw new InvalidOperationException( "Cannot clone from a record with an empty schema." );
			cloned._Columns = new object[_Schema.Count];

			for( int i = 0; i < _Columns.Length; i++ ) cloned._Columns[i] = TypeHelper.TryClone( _Columns[i] );
			cloned._Schema = cloneSchema ? _Schema.Clone() : _Schema;
			cloned._Sealed = _Sealed;
			cloned._SerializeSchema = _SerializeSchema;
			return cloned;
		}