I think i've asked this before, but never gotten to a concrete solution....
Say I have a class Table. This class as a List of type Filter that is a generic type. The filter class looks like this :
Expand|Select|Wrap|Line Numbers
- abstract public class Filter<T>
- {
- /// <summary>
- /// Creates a new TableFilter that can be applied to a Table object.
- /// </summary>
- /// <param name="Column">The column to apply the filter on.</param>
- /// <param name="Criteria">The criteria of the filter to apply.</param>
- public Filter(String column, params T[] criteria)
- {
- Column = column;
- Criteria = criteria;
- }
- /// <summary>
- /// Gets or sets the name of the column to apply the Criteria filter on.
- /// </summary>
- public String Column
- {
- get { return m_column; }
- set { m_column = value; }
- }
- /// <summary>
- /// Gets or sets the Criteria to apply to the selected column.
- /// This Criteria needs to match the Syntax of SQL.
- /// To supplie multiple values, seperate the values with a ;
- /// </summary>
- public T[] Criteria
- {
- get { return m_criteria; }
- set { m_criteria = value; }
- }
- private String m_column; // The column to apply the filter on.
- private T[] m_criteria; // The criteria of the filter.
- }
- Filter<int>("name", value)
- Filter<string>("name", value)
- Filter<bool>("name", value)
I've designed my class Table like this:
Expand|Select|Wrap|Line Numbers
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Data.Common;
- using System.Linq;
- using System.Text;
- using NexusDB.ADOProvider;
- using NexusLink.r9_4.Filters;
- namespace NexusLink.r9_4
- {
- public abstract class Table
- {
- /// <summary>
- /// Creates a new instance of the table with the given name and uses the default
- /// settings to establish a connection to the database.
- /// </summary>
- /// <param name="name">The name of the table to map on.</param>
- public Table(String name) : this(name, new DatabaseSettings()) { }
- /// <summary>
- /// Creates a new instance of the table with a given name and the specified settings
- /// to establish a connection to the database.
- /// </summary>
- /// <param name="name">The name of the table to map on.</param>
- /// <param name="settings">The settings to establish a connection to the database.</param>
- public Table(String name, DatabaseSettings settings)
- {
- Name = name;
- m_command = DbProviderFactories.GetFactory("NexusDB.ADOProvider").CreateCommand();
- m_connection = DbProviderFactories.GetFactory("NexusDB.ADOProvider").CreateConnection();
- m_reader = null;
- m_filters = new List<Filter<T>>();
- m_lock = new object();
- Settings = settings;
- // Configure the command and the connection.
- m_command.Connection = m_connection;
- }
- /// <summary>
- /// Gets the name of the table.
- /// </summary>
- public String Name
- {
- get { return m_name; }
- protected set { m_name = value; }
- }
- /// <summary>
- /// Gets or sets the settings for the table and the database connection.
- /// </summary>
- public DatabaseSettings Settings
- {
- get { return m_settings; }
- set { m_settings = value; }
- }
- /// <summary>
- /// Adds a new filter to the table.
- /// </summary>
- /// <param name="filter">The filter to add to the table.</param>
- public void AddFilter(Filter<object> filter)
- {
- lock (m_lock)
- {
- m_filters.Add(filter);
- }
- }
- /// <summary>
- /// Removes all the filters currently placed on the table.
- /// </summary>
- public void ClearFilters()
- {
- lock (m_lock)
- {
- m_filters.Clear();
- }
- }
- /// <summary>
- /// Advances the table to the next row in the result set.
- /// </summary>
- /// <returns>True if the next row is available; otherwise false.</returns>
- public bool Next()
- {
- // Obtain a lock on the table for exclusive access.
- lock (m_lock)
- {
- // Advance the datareader.
- return m_reader.NextResult();
- }
- }
- /// <summary>
- /// Returns the current row containing data.
- /// </summary>
- /// <returns>A TableRow object holding the data.</returns>
- public TableRow GetCurrentRow()
- {
- throw new NotImplementedException();
- }
- /// <summary>
- /// Opens the connection to the database and retrieves the data for the
- /// table based upon the filters set on the table.
- /// </summary>
- /// <returns>True if the connection was successfully established; otherwise false</returns>
- public bool Open()
- {
- // Obtain a lock on our lockable object so we have exclusive access to the
- // table object and the internals.
- lock (m_lock)
- {
- // Configure the Connection object to connect to the database with
- // the settings that have been applied to our table object.
- m_connection.ConnectionString = m_settings.ToString();
- // Now we need to configure the command object to select the table from the
- // the table we're representing. The selection of the data depends on the filters
- // that have been applied to our table.
- if (m_filters.Count > 0)
- {
- // Filters have been applied to the Table. Create the statement including
- // the filters.
- m_command.CommandText = String.Format("SELECT * FROM {0} WHERE ", Name);
- // Add all the filters.
- foreach (Filter<object> f in m_filters)
- {
- // Add the filter, and add " AND " if it's not the last filter.
- if (m_filters.IndexOf(f) == (m_filters.Count - 1)) m_command.CommandText += f.ToString();
- else m_command.CommandText += f.ToString() + " AND ";
- }
- // Add the final ;
- m_command.CommandText += ";";
- }
- else
- {
- // No filters have been applied on the table, so just select the
- // raw data from the table.
- m_command.CommandText = String.Format("SELECT * FROM {0};", Name);
- }
- // Now that the SQL Code has been generated, apply the last settings to the Command.
- m_command.CommandType = CommandType.Text;
- m_command.CommandTimeout = 10000;
- // Surround the entire connection attempt with a try-catch statement to prevent
- // errors from breaking the code.
- try
- {
- // Open the connection.
- m_reader = m_command.ExecuteReader(CommandBehavior.CloseConnection);
- // Return true because we suceeded.
- return true;
- }
- catch
- {
- // Could not establish a connection, return false.
- return false;
- }
- }
- }
- /// <summary>
- /// Closes the connection to the database.
- /// </summary>
- public void Close()
- {
- // Obtain a lock on our lockable object so we have exclusive access
- // to our table object.
- lock (m_lock)
- {
- // Close the datareader first.
- m_reader.Close();
- // Close the connection.
- m_connection.Close();
- }
- }
- /// <summary>
- /// Inserts a new row into the table at the end with the specified values.
- /// </summary>
- /// <param name="row">The row to insert into the table.</param>
- /// <returns>True if the row was successfully inserts; otherwise false.</returns>
- public bool InsertRow(TableRow row)
- {
- throw new NotImplementedException();
- }
- private String m_name;
- private List<Filter<object>> m_filters;
- private DatabaseSettings m_settings;
- private IDbCommand m_command;
- private IDbConnection m_connection;
- private IDataReader m_reader;
- private object m_lock;
- }
- }
Is there a way around this, that I can have 1 List<Filter<something>> as datamember that allows me to store multiple Filter types?
I can't make the table class Generic, as that serves no purpose in the design.