Class QueryProviderBase<RowType>
This is the base class for ArchiveProviders that use a database query to get their data. Other ways of making archive providers exist, such as TypedInMemoryProviderBase, where the data source is something else and the data are simply buffered by the base class.
Inheritance
Implements
Inherited Members
Namespace: SuperOffice.CRM.ArchiveLists
Assembly: SoDataBase.BusinessLogic.dll
Syntax
public abstract class QueryProviderBase<RowType> : ExtensibleColumnsBase, IArchiveProviderQueryMapping, IArchiveQueryProvider, IArchiveProviderExtensible, IArchiveProvider, IArchiveProviderHasRows, IArchiveProviderHasColumns, IArchiveProviderHasEntities where RowType : ArchiveRow, new()
Type Parameters
| Name | Description |
|---|---|
| RowType |
Remarks
Classes derived from this class will generally have the following structure:
Constructors
QueryProviderBase()
This is the base class for ArchiveProviders that use a database query to get their data. Other ways of making archive providers exist, such as TypedInMemoryProviderBase, where the data source is something else and the data are simply buffered by the base class.
Declaration
protected QueryProviderBase()
Remarks
Classes derived from this class will generally have the following structure:
Fields
_colGetAllRows
Dummy column present in all archives; used in restrictions to specifically request a non-restricted read from the database.
Declaration
protected ArchiveColumnInfo _colGetAllRows
Field Value
| Type | Description |
|---|---|
| ArchiveColumnInfo |
Remarks
Classes derived from this class will generally have the following structure:
_colGetNoRows
This is the base class for ArchiveProviders that use a database query to get their data. Other ways of making archive providers exist, such as TypedInMemoryProviderBase, where the data source is something else and the data are simply buffered by the base class.
Declaration
protected ArchiveColumnInfo _colGetNoRows
Field Value
| Type | Description |
|---|---|
| ArchiveColumnInfo |
Remarks
Classes derived from this class will generally have the following structure:
_pageNumber
This is the base class for ArchiveProviders that use a database query to get their data. Other ways of making archive providers exist, such as TypedInMemoryProviderBase, where the data source is something else and the data are simply buffered by the base class.
Declaration
protected int _pageNumber
Field Value
| Type | Description |
|---|---|
| int |
Remarks
Classes derived from this class will generally have the following structure:
_pageSize
This is the base class for ArchiveProviders that use a database query to get their data. Other ways of making archive providers exist, such as TypedInMemoryProviderBase, where the data source is something else and the data are simply buffered by the base class.
Declaration
protected int _pageSize
Field Value
| Type | Description |
|---|---|
| int |
Remarks
Classes derived from this class will generally have the following structure:
Properties
DropTablesFromPhaseTwo
The fields in this enumeration will be dropped from a Phase Two query; that may also cause one or more tables to be dropped. A useful optimization in a very small number of cases (where fields/joins are only used for Phase One/AcceptRow processing)
Declaration
protected virtual TableInfo[] DropTablesFromPhaseTwo { get; }
Property Value
| Type | Description |
|---|---|
| TableInfo[] |
Remarks
Classes derived from this class will generally have the following structure:
HaveReadToEnd
If all subproviders have been read all the way, then this is set to true
Declaration
protected bool HaveReadToEnd { get; }
Property Value
| Type | Description |
|---|---|
| bool |
Remarks
Classes derived from this class will generally have the following structure:
InhibitDistinctPrimaryKeys
Override this property and return TRUE if you wish to disable the check for distinct primary keys. This will save some time and space, at the cost of potential duplicate rows that would otherwise have been discarded
Declaration
public virtual bool InhibitDistinctPrimaryKeys { get; }
Property Value
| Type | Description |
|---|---|
| bool |
Remarks
Classes derived from this class will generally have the following structure:
InhibitTwoPhaseQuery
Queries are usually run in two phases, one to determine the result set and the other to actually include all joins and fields. This can be inhibited if needed
Declaration
protected bool InhibitTwoPhaseQuery { get; set; }
Property Value
| Type | Description |
|---|---|
| bool |
Remarks
Classes derived from this class will generally have the following structure:
OrderBySlots
The Order By storage system of this archive provider
Declaration
public override OrderByStorage OrderBySlots { get; }
Property Value
| Type | Description |
|---|---|
| OrderByStorage |
Overrides
Remarks
Classes derived from this class will generally have the following structure:
PrimaryKey
The primary key, whose values are used by the duplicate eliminator
Declaration
protected FieldInfo PrimaryKey { get; set; }
Property Value
| Type | Description |
|---|---|
| FieldInfo |
Remarks
Classes derived from this class will generally have the following structure:
PrimaryTable
The primary table of this archive provider, from the derived class
Declaration
public abstract TableInfo PrimaryTable { get; }
Property Value
| Type | Description |
|---|---|
| TableInfo |
Remarks
Classes derived from this class will generally have the following structure:
Query
The main query of this archive provider, from the derived class
Declaration
public abstract ArchiveSelect Query { get; }
Property Value
| Type | Description |
|---|---|
| ArchiveSelect |
Remarks
Classes derived from this class will generally have the following structure:
RootExtenders
Implement this property to return the extender(s) that form the root of the query tree, or null if that is not meaningful. This property is used by the dynamic column processing, which will fail and throw an exception if null is returned here (no problem if dynamic column syntax is not used)
Declaration
protected abstract List<IArchiveExtender> RootExtenders { get; }
Property Value
| Type | Description |
|---|---|
| List<IArchiveExtender> |
Remarks
Classes derived from this class will generally have the following structure:
RootQuery
The main query of this archive provider
Declaration
public override ArchiveSelect RootQuery { get; }
Property Value
| Type | Description |
|---|---|
| ArchiveSelect |
Overrides
Remarks
Classes derived from this class will generally have the following structure:
TableToExtend
The primary table of this archive provider
Declaration
public override TableInfo TableToExtend { get; }
Property Value
| Type | Description |
|---|---|
| TableInfo |
Overrides
Remarks
Classes derived from this class will generally have the following structure:
ValueOverrides
This is the base class for ArchiveProviders that use a database query to get their data. Other ways of making archive providers exist, such as TypedInMemoryProviderBase, where the data source is something else and the data are simply buffered by the base class.
Declaration
protected Dictionary<string, string> ValueOverrides { get; }
Property Value
| Type | Description |
|---|---|
| Dictionary<string, string> |
Remarks
Classes derived from this class will generally have the following structure:
Methods
AcceptRow(SoDataReader)
Decide whether the current row of the passed-in _reader should be accepted or not. If false is returned, this row is skipped by the base class and never seen by the client. This method is called very early, before any ArchiveRow population, and can only rely on fields directly accessible in the Reader. On the other hand, that makes is reasonably cheap to skip rows.
If you implement this method, you MUST aslo implement RequiredPhaseOneFields() to tell the query rewriter about fields you need, otherwise they will not be present in the phase one query and you will crash.Declaration
protected virtual bool AcceptRow(SoDataReader reader)
Parameters
| Type | Name | Description |
|---|---|---|
| SoDataReader | reader |
Returns
| Type | Description |
|---|---|
| bool | true if the current row should be further processed |
Remarks
Classes derived from this class will generally have the following structure:
AddInhibitedStyleHint(string)
Add a style hint to the list of style hints that should be hidden (not be present in the final result rows)
Declaration
public void AddInhibitedStyleHint(string stylehint)
Parameters
| Type | Name | Description |
|---|---|---|
| string | stylehint |
Remarks
Classes derived from this class will generally have the following structure:
Close()
Call this method after the last desired row has been read; this gives the provider the chance to close and free any underlying queries.
Declaration
public virtual void Close()
Remarks
Classes derived from this class will generally have the following structure:
ConvertToTypedRowsAsync(IAsyncEnumerable<ArchiveRow>)
Convert a generic ArchiveRow into some typed subclass, provided the passed-in rows are actually castable
Declaration
protected IAsyncEnumerable<RowType> ConvertToTypedRowsAsync(IAsyncEnumerable<ArchiveRow> genericRows)
Parameters
| Type | Name | Description |
|---|---|---|
| IAsyncEnumerable<ArchiveRow> | genericRows | Enumerable of generic rows that are actually a typed subclass |
Returns
| Type | Description |
|---|---|
| IAsyncEnumerable<RowType> | Enumerable of case, typed rows |
Remarks
Classes derived from this class will generally have the following structure:
CreateArchiveRow(string, int)
Create the archive row object. Providers that offer a strongly typed interface should override this method and create their strongly typed row instead of leaving this generic implementation to make the generic one.
Declaration
protected virtual RowType CreateArchiveRow(string entityName, int primaryKey)
Parameters
| Type | Name | Description |
|---|---|---|
| string | entityName | name of entity represented by this row |
| int | primaryKey | Primary key value of this row |
Returns
| Type | Description |
|---|---|
| RowType | Empty row |
Remarks
Classes derived from this class will generally have the following structure:
GetAllExtenders()
This is the base class for ArchiveProviders that use a database query to get their data. Other ways of making archive providers exist, such as TypedInMemoryProviderBase, where the data source is something else and the data are simply buffered by the base class.
Declaration
public IEnumerable<IArchiveExtender> GetAllExtenders()
Returns
| Type | Description |
|---|---|
| IEnumerable<IArchiveExtender> |
Remarks
Classes derived from this class will generally have the following structure:
GetAvailableEntities()
Get all entities declared by this provider and its extenders
Declaration
public virtual List<ArchiveRowTypeInfo> GetAvailableEntities()
Returns
| Type | Description |
|---|---|
| List<ArchiveRowTypeInfo> | List of available entities |
Remarks
Classes derived from this class will generally have the following structure:
GetEntityName(SoDataReader)
Return the entity name of the current row. The default implementation statically assigns the name of the first registered entity to all rows. Subclasses may override this method if they wish to set other entity names, possibly dependent on data.
Declaration
protected virtual string GetEntityName(SoDataReader _reader)
Parameters
| Type | Name | Description |
|---|---|---|
| SoDataReader | _reader | _reader with the current data row |
Returns
| Type | Description |
|---|---|
| string | Entity name |
Remarks
Classes derived from this class will generally have the following structure:
GetFinalRowCount()
Actual number of rows in query, valid only when HaveReadToEnd = true; otherwise you get -1
Declaration
protected int GetFinalRowCount()
Returns
| Type | Description |
|---|---|
| int |
Remarks
Classes derived from this class will generally have the following structure:
GetReaderAsync(string, CancellationToken)
Start the reader and return an IDataReader (which, as we remember, also inherits IDataRecord for access to individual data fields). This provides an alternative, more generic and more standards-based interface to data. Use either GetRows or GetReader on any particular archive provider instance.
Declaration
public virtual Task<DbDataReader> GetReaderAsync(string options, CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| string | options | |
| CancellationToken | cancellationToken |
Returns
| Type | Description |
|---|---|
| Task<DbDataReader> |
Remarks
Classes derived from this class will generally have the following structure:
GetResultInformationAsync()
Get additional information about the result, such as row count or other optional items. This method should be called after GetRows, but before Close.
Declaration
public Task<ArchiveResultInformation> GetResultInformationAsync()
Returns
| Type | Description |
|---|---|
| Task<ArchiveResultInformation> |
Remarks
Classes derived from this class will generally have the following structure:
GetRowsAsync(string, CancellationToken)
Pass the built-up query to the database; perform paging; and pass populated rows back to the caller.
Declaration
public virtual IAsyncEnumerable<ArchiveRow> GetRowsAsync(string options, CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| string | options | |
| CancellationToken | cancellationToken |
Returns
| Type | Description |
|---|---|
| IAsyncEnumerable<ArchiveRow> |
Remarks
This method calls the following derived-class overrides, in the following order:
HandleDynamicExtenders(IArchiveExtender)
This is the base class for ArchiveProviders that use a database query to get their data. Other ways of making archive providers exist, such as TypedInMemoryProviderBase, where the data source is something else and the data are simply buffered by the base class.
Declaration
protected virtual void HandleDynamicExtenders(IArchiveExtender dynamicTree)
Parameters
| Type | Name | Description |
|---|---|---|
| IArchiveExtender | dynamicTree |
Remarks
Classes derived from this class will generally have the following structure:
InnerMapFieldsAsync(CancellationToken)
Override this method to map query fields to columns, add additional return fields to the query, and set up custom restriction handling
Declaration
public virtual Task InnerMapFieldsAsync(CancellationToken cancellationToken = default)
Parameters
| Type | Name | Description |
|---|---|---|
| CancellationToken | cancellationToken |
Returns
| Type | Description |
|---|---|
| Task |
Remarks
Classes derived from this class will generally have the following structure:
InnerSetRestriction(ArchiveRestrictionInfo[])
Override this method to implement custom processing during SetRestriction, without killing the default implementation
Declaration
public virtual bool InnerSetRestriction(ArchiveRestrictionInfo[] restrictions)
Parameters
| Type | Name | Description |
|---|---|---|
| ArchiveRestrictionInfo[] | restrictions | Incoming array of restrictions |
Returns
| Type | Description |
|---|---|
| bool | True if at least one active restriction matched a known column and was processed |
Remarks
Classes derived from this class will generally have the following structure:
OverrideValueIfBlank(ArchiveRow, string, string)
This is the base class for ArchiveProviders that use a database query to get their data. Other ways of making archive providers exist, such as TypedInMemoryProviderBase, where the data source is something else and the data are simply buffered by the base class.
Declaration
protected bool OverrideValueIfBlank(ArchiveRow row, string columnToOverride, string alternativeSource)
Parameters
| Type | Name | Description |
|---|---|---|
| ArchiveRow | row | |
| string | columnToOverride | |
| string | alternativeSource |
Returns
| Type | Description |
|---|---|
| bool |
Remarks
Classes derived from this class will generally have the following structure:
PostProcessQuery()
This method is called after ModifyQuery has been called on all extenders, but before the query is executed. It is used for processing that needs the query to be 'complete' from the extenders, and gives the opportunity to tweak it, for instance by adding return fields needed for some particular functionality.
Declaration
public virtual void PostProcessQuery()
Remarks
Classes derived from this class will generally have the following structure:
PostProcessRow(SoDataReader, ArchiveRow)
This method is a hook that can be used by derived classes to post-process rows. It is called after all extenders have fetched their data and populated the row.
Declaration
protected virtual void PostProcessRow(SoDataReader _reader, ArchiveRow row)
Parameters
| Type | Name | Description |
|---|---|---|
| SoDataReader | _reader | |
| ArchiveRow | row |
Remarks
Classes derived from this class will generally have the following structure:
RegisterEntity(ArchiveRowTypeInfo)
Register an entity on this provider
Declaration
protected ArchiveRowTypeInfo RegisterEntity(ArchiveRowTypeInfo entity)
Parameters
| Type | Name | Description |
|---|---|---|
| ArchiveRowTypeInfo | entity | Entity to register |
Returns
| Type | Description |
|---|---|
| ArchiveRowTypeInfo | The same entity, so you can go on doing things to it |
Remarks
Classes derived from this class will generally have the following structure:
RequiredPhaseOneFields()
Return the FieldInfo fields needed by AcceptRow(SoDataReader), so that the query rewriter does not drop them. Implement this method IFF you implement AcceptRow.
Declaration
protected virtual FieldInfo[] RequiredPhaseOneFields()
Returns
| Type | Description |
|---|---|
| FieldInfo[] |
Remarks
Classes derived from this class will generally have the following structure:
SetDesiredColumns(params string[])
Set the desired columns, by saving them in an internal data structures. Duplicates are gracefully ignored.
Declaration
public override void SetDesiredColumns(params string[] columnIds)
Parameters
| Type | Name | Description |
|---|---|---|
| string[] | columnIds |
Overrides
Remarks
Classes derived from this class will generally have the following structure:
SetDesiredEntities(params string[])
Set the desired entities
Declaration
public virtual void SetDesiredEntities(params string[] entities)
Parameters
| Type | Name | Description |
|---|---|---|
| string[] | entities | Names of desired entities |
Remarks
Classes derived from this class will generally have the following structure:
SetOrderBy(ArchiveOrderByInfo[])
Set the order by parameters. This method sets the order by parameters of this provider, as well as invoking the same call on all known extenders. Recursion will take it to the bottom. This method actually only saves the orderby specification for use during query processing. Any column name overrides are processed, i.e., replaced with the original inner names, so that the inner providers do not see the overrides.
Declaration
public override void SetOrderBy(ArchiveOrderByInfo[] orderBy)
Parameters
| Type | Name | Description |
|---|---|---|
| ArchiveOrderByInfo[] | orderBy | Array of order by criteria |
Overrides
Remarks
Classes derived from this class will generally have the following structure:
SetPagingInfo(int, int)
Verify the paging information, and set page size and number
Declaration
public void SetPagingInfo(int pageSize, int pageNumber)
Parameters
| Type | Name | Description |
|---|---|---|
| int | pageSize | Page size in rows, 1-2000 or int.MaxValue to disable paging |
| int | pageNumber | 0-based page number |
Remarks
Classes derived from this class will generally have the following structure:
SetRestriction(params ArchiveRestrictionInfo[])
Set the restriction by calling the base class and InnerSetRestriction; take this opportunity to note that a restriction has actually been set, so we can report cases of totally missing restrictions (which is not acceptable as it might end up fetching the whole database)
Declaration
public override bool SetRestriction(params ArchiveRestrictionInfo[] restrictions)
Parameters
| Type | Name | Description |
|---|---|---|
| ArchiveRestrictionInfo[] | restrictions |
Returns
| Type | Description |
|---|---|
| bool |
Overrides
Remarks
Classes derived from this class will generally have the following structure: