//****************************************************************************************************** // ITableOperations.cs - Gbtc // // Copyright © 2016, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this // file except in compliance with the License. You may obtain a copy of the License at: // // http://opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 05/12/2016 - J. Ritchie Carroll // Generated original version of source code. // //****************************************************************************************************** using GSF.ComponentModel; using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Diagnostics.CodeAnalysis; namespace GSF.Data.Model { /// /// Defines a common interface for implementations of . /// public interface ITableOperations { /// /// Gets the table name defined for the modeled table, includes any escaping as defined in model. /// string TableName { get; } /// /// Gets the table name defined for the modeled table without any escape characters. /// /// /// A table name will only be escaped if the model requested escaping with the . /// string UnescapedTableName { get; } /// /// Gets flag that determines if modeled table has a primary key that is an identity field. /// bool HasPrimaryKeyIdentityField { get; } /// /// Gets or sets delegate used to handle table operation exceptions. /// /// /// When exception handler is provided, table operations will not throw exceptions for database calls, any /// encountered exceptions will be passed to handler for processing. Otherwise, exceptions will be thrown /// on the call stack. /// Action ExceptionHandler { get; set; } /// /// Gets or sets flag that determines if field names should be treated as case sensitive. Defaults to false. /// /// /// In cases where modeled table fields have applied , this flag will be used /// to properly update escaped field names that may be case sensitive. For example, escaped field names in Oracle /// are case sensitive. This value is typically false. /// bool UseCaseSensitiveFieldNames { get; set; } /// /// Gets or sets primary key cache. /// /// /// /// The overloads that include paging parameters /// cache the sorted and filtered primary keys of queried records between calls so that paging is fast and /// efficient. Since the primary keys are cached, an instance of the should /// exist per user session when using query functions that support pagination. In web based implementations, /// the primary cache should be stored with user session state data and then restored between instances of /// the that are created along with a connection that is opened per page. /// /// /// The function should be called to manually clear cache when table /// contents are known to have changed. Note that calls to any overload /// will automatically clear any existing primary key cache. /// /// /// Primary keys values are stored in data table without interpretation, i.e., in their raw form as queried /// from the database. Primary key data in cache will be encrypted for models with primary key fields that /// are marked with the /// /// DataTable PrimaryKeyCache { get; set; } /// /// Gets or sets root record restriction that applies to query table operations. /// /// /// /// Defining a root query restriction creates a base query filter that gets applied to all query operations, /// even when another restriction is applied - in this case the root restriction will be pre-pended to the /// specified query, e.g.: /// /// restriction = RootQueryRestriction + restriction; /// /// A root query restriction is useful to apply a common state to the query operations, e.g., always /// filtering records for a specific user or context. /// /// /// A root query restriction can be manually assigned to a instance or /// automatically assigned by marking a model with the . /// /// /// If any of the reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// RecordRestriction RootQueryRestriction { get; set; } /// /// Gets or sets flag that determines if should be applied to update operations. /// /// /// /// If only references primary key fields, then this property value should be set /// to false since default update operations for a modeled record already work against primary key fields. /// /// /// This flag can be manually set per instance or handled automatically by marking /// a model with the and assigning a value to the attribute property /// . /// /// bool ApplyRootQueryRestrictionToUpdates { get; set; } /// /// Gets or sets flag that determines if should be applied to delete operations. /// /// /// /// If only references primary key fields, then this property value should be set /// to false since default delete operations for a modeled record already work against primary key fields. /// /// /// This flag can be manually set per instance or handled automatically by marking /// a model with the and assigning a value to the attribute property /// . /// /// bool ApplyRootQueryRestrictionToDeletes { get; set; } /// /// Creates a new modeled record instance, applying any modeled default values as specified by a /// or on the /// model properties. /// /// New modeled record instance with any defined default values applied. object NewRecord(); /// /// Applies the default values on the specified modeled table /// where any of the properties are marked with either /// or . /// /// Record to update. void ApplyRecordDefaults(object record); /// /// Applies the update values on the specified modeled table where /// any of the properties are marked with . /// /// Record to update. void ApplyRecordUpdates(object record); /// /// Queries database and returns a single modeled table record for the specified . /// /// Record restriction to apply. /// A single modeled table record for the queried record. /// /// /// If no record is found for specified , null will be returned. /// /// /// This is a convenience call to /// specifying the parameter with a limit of 1 record. /// /// /// If any of the parameters reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// object QueryRecord(RecordRestriction restriction); /// /// Queries database and returns a single modeled table record for the specified , /// execution of query will apply . /// /// Field name expression used for sort order, include ASC or DESC as needed - does not include ORDER BY; defaults to primary keys. /// Record restriction to apply. /// A single modeled table record for the queried record. /// /// /// If no record is found for specified , null will be returned. /// /// /// This is a convenience call to /// specifying the parameter with a limit of 1 record. /// /// /// If any of the parameters reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// object QueryRecord(string orderByExpression, RecordRestriction restriction); /// /// Queries database and returns a single modeled table record for the specified SQL filter /// expression and parameters. /// /// /// Filter SQL expression for restriction as a composite format string - does not include WHERE. /// When escaping is needed for field names, use standard ANSI quotes. /// /// Restriction parameter values. /// A single modeled table record for the queried record. /// /// /// If no record is found for specified filter expression and parameters, null will be returned. /// /// /// Each indexed parameter, e.g., "{0}", in the composite format /// will be converted into query parameters where each of the corresponding values in the /// collection will be applied as /// values to an executed query. /// /// /// If any of the specified reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// /// If needed, field names that are escaped with standard ANSI quotes in the filter expression /// will be updated to reflect what is defined in the user model. /// /// /// This is a convenience call to /// specifying the parameter with a limit of 1 record. /// /// object QueryRecordWhere(string filterExpression, params object[] parameters); /// /// Queries database and returns modeled table records for the specified parameters. /// /// Field name expression used for sort order, include ASC or DESC as needed - does not include ORDER BY; defaults to primary keys. /// Record restriction to apply, if any. /// Limit of number of record to return. /// An enumerable of modeled table row instances for queried records. /// /// /// If no record or is provided, all rows will be returned. /// /// /// If any of the parameters reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// IEnumerable QueryRecords(string orderByExpression = null, RecordRestriction restriction = null, int limit = -1); /// /// Queries database and returns modeled table records for the specified . /// /// Record restriction to apply. /// An enumerable of modeled table row instances for queried records. /// /// /// This is a convenience call to only /// specifying the parameter. /// /// /// If any of the parameters reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// IEnumerable QueryRecords(RecordRestriction restriction); /// /// Queries database and returns modeled table records for the specified SQL filter expression /// and parameters. /// /// /// Filter SQL expression for restriction as a composite format string - does not include WHERE. /// When escaping is needed for field names, use standard ANSI quotes. /// /// Restriction parameter values. /// An enumerable of modeled table row instances for queried records. /// /// /// Each indexed parameter, e.g., "{0}", in the composite format /// will be converted into query parameters where each of the corresponding values in the /// collection will be applied as /// values to an executed query. /// /// /// If any of the specified reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// /// If needed, field names that are escaped with standard ANSI quotes in the filter expression /// will be updated to reflect what is defined in the user model. /// /// /// This is a convenience call to only /// specifying the parameter. /// /// IEnumerable QueryRecordsWhere(string filterExpression, params object[] parameters); /// /// Queries database and returns modeled table records for the specified sorting, paging and search parameters. /// Search executed against fields modeled with . /// /// Field name to order-by. /// Sort ascending flag; set to false for descending. /// Page number of records to return (1-based). /// Current page size. /// Text to search. /// An enumerable of modeled table row instances for queried records. /// /// /// This function is used for record paging. Primary keys are cached server-side, typically per user session, /// to maintain desired per-page sort order. Call to manually clear cache /// when table contents are known to have changed. /// /// /// If the specified has been marked with , /// establishing the primary key cache operation will take longer to execute since query data will need to /// be downloaded locally and decrypted so the proper sort order can be determined. /// /// /// This is a convenience call to where restriction /// is generated by using . /// /// IEnumerable QueryRecords(string sortField, bool ascending, int page, int pageSize, string searchText); /// /// Queries database and returns modeled table records for the specified sorting and paging parameters. /// /// Field name to order-by. /// Sort ascending flag; set to false for descending. /// Page number of records to return (1-based). /// Current page size. /// Record restriction to apply, if any. /// An enumerable of modeled table row instances for queried records. /// /// /// This function is used for record paging. Primary keys are cached server-side, typically per user session, /// to maintain desired per-page sort order. Call to manually clear cache /// when table contents are known to have changed. /// /// /// If any of the parameters reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// /// If the specified has been marked with , /// establishing the primary key cache operation will take longer to execute since query data will need to /// be downloaded locally and decrypted so the proper sort order can be determined. /// /// IEnumerable QueryRecords(string sortField, bool ascending, int page, int pageSize, RecordRestriction restriction = null); /// /// Gets the record count for the modeled table based on search parameter. /// Search executed against fields modeled with . /// /// Text to search. /// Record count for the modeled table based on search parameter. /// /// This is a convenience call to where restriction /// is generated by /// int QueryRecordCount(string searchText); /// /// Gets the record count for the specified - or - total record /// count for the modeled table if is null. /// /// Record restriction to apply, if any. /// /// Record count for the specified - or - total record count /// for the modeled table if is null. /// /// /// If any of the parameters reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// int QueryRecordCount(RecordRestriction restriction = null); /// /// Gets the record count for the modeled table for the specified SQL filter expression and parameters. /// /// /// Filter SQL expression for restriction as a composite format string - does not include WHERE. /// When escaping is needed for field names, use standard ANSI quotes. /// /// Restriction parameter values. /// Record count for the modeled table for the specified parameters. /// /// /// Each indexed parameter, e.g., "{0}", in the composite format /// will be converted into query parameters where each of the corresponding values in the /// collection will be applied as /// values to an executed query. /// /// /// If any of the specified reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// /// If needed, field names that are escaped with standard ANSI quotes in the filter expression /// will be updated to reflect what is defined in the user model. /// /// /// This is a convenience call to . /// /// int QueryRecordCountWhere(string filterExpression, params object[] parameters); /// /// Locally searches retrieved table records after queried from database for the specified sorting and search parameters. /// Search executed against fields modeled with . /// Function only typically used for record models that apply the . /// /// Field name to order-by. /// Sort ascending flag; set to false for descending. /// Text to search. /// to use when searching string fields; defaults to ordinal ignore case. /// An array of modeled table row instances for the queried records that match the search. /// /// /// This function searches records locally after query from database, this way functionality will work /// even with fields that are modeled with the and use the . /// Primary keys for this function will not be cached server-side and this function will be slower and more expensive than similar calls /// to . Usage should be restricted to cases searching for field data that has /// been modeled with the . /// /// /// This function does not paginate records, instead a full list of search records is returned. User can cache returned records and page /// through them using the function. As a result, usage should be restricted to smaller data sets. /// /// object[] SearchRecords(string sortField, bool ascending, string searchText, StringComparison comparison = StringComparison.OrdinalIgnoreCase); /// /// Determines if any fields modeled with the match any of the /// specified . /// /// Modeled table record. /// Values to search. /// /// true if any fields modeled with match any of the /// specified ; otherwise, false. /// /// /// String comparisons will be ordinal ignoring case. /// bool IsSearchMatch(object record, params string[] searchValues); /// /// Determines if any fields modeled with the match any of the /// specified . /// /// Modeled table record. /// to use when searching string fields. /// Values to search. /// /// true if any fields modeled with match any of the /// specified ; otherwise, false. /// bool IsSearchMatch(object record, StringComparison comparison, params string[] searchValues); /// /// Gets the specified of records from the provided source array. /// /// Source records array. /// Desired page of records. /// Desired page size. /// A page of records. IEnumerable GetPageOfRecords(object[] records, int page, int pageSize); /// /// Creates a new modeled table record queried from the specified . /// /// Primary keys values of the record to load. /// New modeled table record queried from the specified . object LoadRecord(params object[] primaryKeys); /// /// Creates a new modeled table record queried from the specified . /// /// of queried data to be loaded. /// New modeled table record queried from the specified . object LoadRecord(DataRow row); /// /// Converts the given collection of into a . /// /// The collection of records to be inserted into the data table. /// A data table containing data from the given records. DataTable ToDataTable(IEnumerable records); /// /// Deletes the record referenced by the specified . /// /// Primary keys values of the record to load. /// Number of rows affected. int DeleteRecord(params object[] primaryKeys); /// /// Deletes the specified modeled table from the database. /// /// Record to delete. /// Number of rows affected. int DeleteRecord(object record); /// /// Deletes the record referenced by the specified . /// /// of queried data to be deleted. /// Number of rows affected. int DeleteRecord(DataRow row); /// /// Deletes the records referenced by the specified . /// /// Record restriction to apply /// /// Flag that determines if any existing should be applied. Defaults to /// setting. /// /// Number of rows affected. /// /// If any of the parameters reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// cannot be null. int DeleteRecord(RecordRestriction restriction, bool? applyRootQueryRestriction = null); /// /// Deletes the records referenced by the specified SQL filter expression and parameters. /// /// /// Filter SQL expression for restriction as a composite format string - does not include WHERE. /// When escaping is needed for field names, use standard ANSI quotes. /// /// Restriction parameter values. /// Number of rows affected. /// /// /// Each indexed parameter, e.g., "{0}", in the composite format /// will be converted into query parameters where each of the corresponding values in the /// collection will be applied as /// values to an executed query. /// /// /// If any of the specified reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// /// If needed, field names that are escaped with standard ANSI quotes in the filter expression /// will be updated to reflect what is defined in the user model. /// /// /// This is a convenience call to . /// /// int DeleteRecordWhere(string filterExpression, params object[] parameters); /// /// Updates the database with the specified modeled table , /// any model properties marked with will /// be evaluated and applied before the record is provided to the data source. /// /// Record to update. /// Record restriction to apply, if any. /// /// Flag that determines if any existing should be applied. Defaults to /// setting. /// /// Number of rows affected. /// /// /// Record restriction is only used for custom update expressions or in cases where modeled /// table has no defined primary keys. /// /// /// If any of the parameters reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// int UpdateRecord(object record, RecordRestriction restriction = null, bool? applyRootQueryRestriction = null); /// /// Updates the database with the specified modeled table /// referenced by the specified SQL filter expression and parameters, any model properties /// marked with will be evaluated and applied /// before the record is provided to the data source. /// /// Record to update. /// /// Filter SQL expression for restriction as a composite format string - does not include WHERE. /// When escaping is needed for field names, use standard ANSI quotes. /// /// Restriction parameter values. /// Number of rows affected. /// /// /// Record restriction is only used for custom update expressions or in cases where modeled /// table has no defined primary keys. /// /// /// Each indexed parameter, e.g., "{0}", in the composite format /// will be converted into query parameters where each of the corresponding values in the /// collection will be applied as /// values to an executed query. /// /// /// If any of the specified reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// /// If needed, field names that are escaped with standard ANSI quotes in the filter expression /// will be updated to reflect what is defined in the user model. /// /// /// This is a convenience call to . /// /// int UpdateRecordWhere(object record, string filterExpression, params object[] parameters); /// /// Updates the database with the specified , any model properties /// marked with will be evaluated and applied /// before the record is provided to the data source. /// /// of queried data to be updated. /// Record restriction to apply, if any. /// Number of rows affected. /// /// /// Record restriction is only used for custom update expressions or in cases where modeled /// table has no defined primary keys. /// /// /// If any of the parameters reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// int UpdateRecord(DataRow row, RecordRestriction restriction = null); /// /// Updates the database with the specified referenced by the /// specified SQL filter expression and parameters, any model properties marked with /// will be evaluated and applied before /// the record is provided to the data source. /// /// of queried data to be updated. /// /// Filter SQL expression for restriction as a composite format string - does not include WHERE. /// When escaping is needed for field names, use standard ANSI quotes. /// /// Restriction parameter values. /// Number of rows affected. /// /// /// Record restriction is only used for custom update expressions or in cases where modeled /// table has no defined primary keys. /// /// /// Each indexed parameter, e.g., "{0}", in the composite format /// will be converted into query parameters where each of the corresponding values in the /// collection will be applied as /// values to an executed query. /// /// /// If any of the specified reference a table field that is modeled with /// either an or , then the function /// will need to be called, replacing the target parameter with the /// returned value so that the field value will be properly set prior to executing the database function. /// /// /// If needed, field names that are escaped with standard ANSI quotes in the filter expression /// will be updated to reflect what is defined in the user model. /// /// /// This is a convenience call to . /// /// int UpdateRecordWhere(DataRow row, string filterExpression, params object[] parameters); /// /// Adds the specified modeled table to the database. /// /// Record to add. /// Number of rows affected. int AddNewRecord(object record); /// /// Adds the specified to the database. /// /// of queried data to be added. /// Number of rows affected. int AddNewRecord(DataRow row); /// /// Adds the specified modeled table to the database if the /// record has not defined any of its primary key values; otherwise, the database will /// be updated with the specified modeled table . /// /// Record to add or update. /// Number of rows affected. int AddNewOrUpdateRecord(object record); /// /// Gets the primary key values from the specified . /// /// Record of data to retrieve primary keys from. /// Primary key values from the specified . object[] GetPrimaryKeys(object record); /// /// Gets the primary key values from the specified . /// /// of queried data. /// Primary key values from the specified . /// /// Function returns raw data from without interpretation, it may be /// necessary to call for models with primary key /// fields that are marked with either or /// . /// object[] GetPrimaryKeys(DataRow row); /// /// Gets the field names for the table; if is true, also includes any escaping as defined in model. /// /// Flag that determines if field names should include any escaping as defined in the model; defaults to true. /// Array of field names. /// /// A field name will only be escaped if the model requested escaping with the . /// string[] GetFieldNames(bool escaped = true); /// /// Get the primary key field names for the table; if is true, also includes any escaping as defined in model. /// /// Flag that determines if field names should include any escaping as defined in the model; defaults to true. /// Array of primary key field names. /// /// A field name will only be escaped if the model requested escaping with the . /// string[] GetPrimaryKeyFieldNames(bool escaped = true); /// /// Attempts to get the specified for a field. /// /// Type of attribute to attempt to get. /// Name of field to use for attribute lookup. /// Attribute that was found, if any. /// true if attribute was found; otherwise, false. bool TryGetFieldAttribute(string fieldName, out TAttribute attribute) where TAttribute : Attribute; /// /// Attempts to get the specified for a field. /// /// Name of field to use for attribute lookup. /// Type of attribute to attempt to get. /// Attribute that was found, if any. /// true if attribute was found; otherwise, false. /// is not an . bool TryGetFieldAttribute(string fieldName, Type attributeType, out Attribute attribute); /// /// Determines if the specified field has an associated attribute. /// /// Type of attribute to search for. /// Name of field to use for attribute lookup. /// true if field has attribute; otherwise, false. [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")] bool FieldHasAttribute(string fieldName) where TAttribute : Attribute; /// /// Determines if the specified field has an associated attribute. /// /// Name of field to use for attribute lookup. /// Type of attribute to search for. /// true if field has attribute; otherwise, false. /// is not an . bool FieldHasAttribute(string fieldName, Type attributeType); /// /// Gets the value for the specified field. /// /// Modeled table record. /// Field name to retrieve. /// Field value or null if field is not found. object GetFieldValue(object record, string fieldName); /// /// Gets the interpreted value for the specified field, encrypting or returning any intermediate /// value as needed. /// /// Field name to retrieve. /// Field value to use. /// /// Interpreted value for the specified field, encrypting or returning any intermediate value /// as needed. /// /// /// /// This function will need to be used when calling overloads that take a or composite format /// filter expression where the or have been modeled /// on a field referenced by one of the parameters. Since the record restrictions are used /// with a free-form expression, the class cannot be aware of the fields accessed in the /// expression without attempting to parse the expression which would be time consuming and error prone; as a result, users /// will need to be aware to call this function when using record restriction that references fields that are either marked /// for encryption or use a specific field data-type attribute. /// /// /// If a parameter references a field that is modeled with an , /// this function will need to be called, replacing the restriction parameter with the returned value, so that the field data /// value will be properly encrypted prior to executing the database function. /// /// /// If a parameter references a field that is modeled with a , /// this function will need to be called, replacing the restriction parameter with the returned value, so that the field data /// type will be properly set prior to executing the database function. /// /// object GetInterpretedFieldValue(string fieldName, object value); /// /// Gets the for the specified field. /// /// Field name to retrieve. /// Field or null if field is not found. Type GetFieldType(string fieldName); /// /// Generates a based on fields marked with and specified . /// /// Text to search. /// based on fields marked with and specified . /// /// Any fields marked with both and will be automatically managed, i.e., /// the returned parameters will already apply any field based encryption as needed. Database query functions /// executed for fields marked for encryption will only be searched using , regardless of any otherwise /// specified value in the as encryption is handled locally. However, the function /// can be used to find data in encrypted fields that are marked for search with a . /// RecordRestriction GetSearchRestriction(string searchText); /// /// Calculates the size of the current primary key cache, in number of records. /// /// Number of records in the current primary key cache. int GetPrimaryKeyCacheSize(); /// /// Clears the primary key cache for this instance. /// /// /// /// This method is intended to be used in conjunction with calls to the overloads for /// which are /// used for record pagination. /// /// /// If record set is known to have changed outside purview of this class, this method /// should be called so that primary key cache can be reloaded. /// /// void ClearPrimaryKeyCache(); } }