Example #1
0
		protected virtual void Dispose( bool disposing )
		{
			DEBUG.IndentLine( "\n-- KRecordBuilder.Dispose( Disposing={0} ) - This={1}", disposing, this );
			if( _Values != null ) { _Values.Clear(); _Values = null; }
			_Schema = null; // It might be in use elsewhere
			DEBUG.Unindent();
		}
Example #2
0
		private KRecord() { } // For the specialized Clone() and Changes() methods...

		/// <summary>
		/// Creates a new <see cref="KRecord"/> instance using the given schema to define its columns.
		/// <para>The schema will be sealed in order to avoid changes to it (because the structure of the record is created
		/// in this constructor, but the record does not keep track of any future changes in the schema).</para>
		/// </summary>
		/// <param name="schema">The schema defining the columns in this record.</param>
		public KRecord( KSchema schema )
		{
			DEBUG.IndentLine( "\n-- KRecord( Schema={0} )", schema == null ? "null" : schema.ToString() );

			if( ( _Schema = schema ) == null ) throw new ArgumentNullException( "schema", "Schema cannot be null." );
			if( _Schema.Count <= 0 ) throw new ArgumentException( "Invalid number of columns in schema: " + _Schema );
			_Schema.Sealed = true;
			_Columns = new object[_Schema.Count];

			DEBUG.Unindent();
		}
Example #3
0
		protected virtual void Dispose( bool disposing )
		{
			DEBUG.IndentLine( "\n-- KRecord.Dispose( Disposing={0} ) - This={1}", disposing, this );

			if( _Columns != null ) {
				for( int i = 0; i < _Columns.Length; i++ ) _Columns[i] = null;
				_Columns = null;
			}
			_Schema = null; // Might be in use elsewhere

			DEBUG.Unindent();
		}
Example #4
0
		protected override void Dispose( bool disposing )
		{
			DEBUG.IndentLine( "\n-- KEnumeratorWCF.Dispose( Disposing={0} ) - This={1}", disposing, this );

			if( _EnumeratorId != Guid.Empty ) {
				if( Link != null && Link.Proxy != null ) Link.Proxy.EnumeratorDispose( _EnumeratorId );
				_EnumeratorId = Guid.Empty;
			}
			_Schema = null;

			base.Dispose( disposing ); // Calls-back Reset() - but with no effects...
			DEBUG.Unindent();
		}
Example #5
0
		/// <summary>
		/// Advances this enumerator to return the next element from the database.
		/// <para>In this implementation these elements are not maintained in an in-memory structure, but rather are retrieved
		/// and maintained in the CurrentRecord property just until the next invocation of MoveNext().
		/// </summary>
		/// <returns>True if the next element has been obtained, false if there are no more elements available.</returns>
		public override bool MoveNext()
		{
			// First iteration...
			if( _Surrogate == null ) {
				_Surrogate = new KSurrogate( this.Command, iterable: true );
				_Schema = _Surrogate._Schema;
			}

			// If we have finished, cleaning it up...
			if( !_Surrogate._DataReader.Read() ) {
				DEBUG.IndentLine( "\n-- MoveNext: null" ); DEBUG.Unindent();
				_Surrogate.Dispose(); _Surrogate = null;
				return false;
			}

			// Else, generating the record...			
			_CurrentRecord = new KRecord( _Schema ); for( int i = 0; i < _Schema.Count; i++ ) {
				object value = _Surrogate._DataReader.IsDBNull( i ) ? null : _Surrogate._DataReader.GetValue( i );
				_CurrentRecord[i] = value;
			}
			DEBUG.IndentLine( "\n-- MoveNext: {0}", CurrentRecord.ToString() ); DEBUG.Unindent();
			return true;
		}
Example #6
0
		/// <summary>
		/// Resets this enumerator.
		/// </summary>
		public override void Reset()
		{
			if( _EnumeratorId != Guid.Empty ) {
				if( Link != null && Link.Proxy != null ) Link.Proxy.EnumeratorReset( _EnumeratorId );
				_EnumeratorId = Guid.Empty;
			}
			_Schema = null; // Do not dispose, might be in use elsewhere...
		}
Example #7
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;
		}
Example #8
0
		protected KRecord( SerializationInfo info, StreamingContext context )
		{
			int count = (int)info.GetValue( "ColumnCount", typeof( int ) );
			_Columns = new object[count];

			for( int i = 0; i < count; i++ ) {
				string type = info.GetString( "ColumnType" + i );
				object value = type == "VOID" ? null : info.GetValue( "ColumnValue" + i, Type.GetType( type ) );
				_Columns[i] = value;
			}

			_Sealed = info.GetBoolean( "RecordSealed" );

			_SerializeSchema = info.GetBoolean( "SerializeSchema" );
			if( _SerializeSchema ) _Schema = (KSchema)info.GetValue( "Schema", typeof( KSchema ) );
		}
Example #9
0
		/// <summary>
		/// Resets this enumerator.
		/// </summary>
		public override void Reset()
		{
			if( _Surrogate != null ) { _Surrogate.Dispose(); _Surrogate = null; }
			_Schema = null;
			_CurrentRecord = null;
		}
Example #10
0
		void Invoke( bool iterable )
		{
			// Opening if needed...
			if( !_Link.IsDbOpened ) { _Link.DbOpen(); _LinkOpenedBySurrogate = true; }

			// Creating the database command and its parameters...
			IDbCommand cmd = _Link.DbConnection.CreateCommand();
			cmd.CommandText = _Command.CommandText( iterable );

			string nullStr = _Command.Parser.Parse( null, nulls: true ); // To substitute parameters with NULL values...
			foreach( var par in _Command.Parameters ) {
				if( par.Value == null ) cmd.CommandText = cmd.CommandText.Replace( par.Name, nullStr );
				else {
					IDataParameter dbpar = cmd.CreateParameter();
					dbpar.ParameterName = par.Name;
					dbpar.Value = _Link.TransformParameterValue( par.Value );
					cmd.Parameters.Add( dbpar );
				}
			}

			// Setting the transaction...
			Transaction scope = Transaction.Current; if( scope != null ) { } // Managed by TransactionScope
			else {
				IDbTransaction tx = null; // Using the current connection's transaction, if exists...

				var innerConnection = TypeHelper.GetElementValue( _Link.DbConnection, "InnerConnection" );
				if( innerConnection != null ) {
					var currentTransaction = TypeHelper.GetElementValue( innerConnection, "CurrentTransaction" );
					if( currentTransaction != null ) {
						var parent = TypeHelper.GetElementValue( currentTransaction, "Parent" );
						if( parent != null ) tx = (IDbTransaction)parent;
					}
				}
				if( tx != null ) cmd.Transaction = tx;
			}

			// Execute if NON-QUERY...
			if( !iterable ) {
				try { _NonQueryResult = cmd.ExecuteNonQuery(); }
				catch { throw; }
				finally { cmd.Dispose(); cmd = null; }
				return;
			}

			// OTHERWISE, we need to capture the datareader and the schema returned from the database...
			try { _DataReader = cmd.ExecuteReader( CommandBehavior.KeyInfo ); }
			catch { throw; }
			finally { cmd.Dispose(); cmd = null; }

			// Creating the schema...
			DataTable table = _DataReader.GetSchemaTable();
			if( table == null ) throw new InvalidOperationException( "Cannot obtain schema table for command: " + cmd );

			string tablename = _Command is IKTableNameProvider ? ( (IKTableNameProvider)_Command ).TableName : null;

			_Schema = new KSchema( _Link.DbCaseSensitiveNames ); for( int i = 0; i < table.Rows.Count; i++ ) {
				DataRow row = table.Rows[i];
				string meta = null;
				object value = null;

				bool hidden = false; if( table.Columns.Contains( "IsHidden" ) ) {
					value = row[table.Columns["IsHidden"]];
					if( !( value is DBNull ) ) hidden = (bool)value;
				}
				if( hidden ) continue;

				KMetaColumn column = new KMetaColumn(); for( int j = 0; j < table.Columns.Count; j++ ) {
					meta = table.Columns[j].ColumnName;
					value = row[j] is DBNull ? null : row[j];
					if( value != null ) column[meta] = value;
				}
				if( column.BaseTableName == null && tablename != null ) column.BaseTableName = tablename;
				DEBUG.WriteLine( "-- Schema Column: {0}", column );
				_Schema.Add( column );
			}
			table.Dispose(); table = null;

			// Setting the aliases if needed...
			if( _Command is IKTableAliasListProvider )
				_Schema.TableAliasList.AddRange( ( (IKTableAliasListProvider)_Command ).TableAliasList );

			// And finishing with the schema...
			_Schema.Sealed = true;
		}
Example #11
0
		protected virtual void Dispose( bool disposing )
		{
			DEBUG.IndentLine( "\n-- KSurrogate.Dispose( Disposing={0} ) - This={1}", disposing, this );

			if( _DataReader != null ) {
				if( !_DataReader.IsClosed ) _DataReader.Close();
				_DataReader.Dispose();
				_DataReader = null;
			}
			if( _Link != null ) {
				if( _LinkOpenedBySurrogate ) _Link.DbClose();
				_Link = null;
			}

			_Schema = null; // It might be in use elsewhere
			_Command = null;

			DEBUG.Unindent();
		}
Example #12
0
		/// <summary>
		/// Creates a new instance of <see cref="KRecordBuilder"/>.
		/// <para>Its TableAliasList property can be used to add the aliases needed for the schema.</para>
		/// </summary>
		/// <param name="caseSensitiveNames">Whether the names of tables and columns are considered case sensitively or
		/// not.</param>
		public KRecordBuilder( bool caseSensitiveNames )
		{
			DEBUG.IndentLine( "\n-- KRecordBuilder( CaseSensitive={0} )", caseSensitiveNames );
			_Schema = new KSchema( caseSensitiveNames );
			DEBUG.Unindent();
		}