Create a Fragment Provider

A fragment provider is a class that implements the IQueryFragmentProvider interface. It is designed to promote reusability among various queries without resorting to having to provide raw SQL to attain that reusability. As with IParameterProvider objects, these are not required.

Fragment providers can be model objects, or can be part of an IDatabaseQueryProvider class. Putting fragments in the model class can remind developers to add new properties to the query for that class; however, it means that SQL is in two places, and that the model must be specified when the master query library is built. Putting them in a query provider may result in developers forgetting to add new properties to the fragments; however, the SQL is in one place, and fragments are automatically derived if the query provider also provides them. Which of these is more preferable is a decision left to the implementer; even within the DatabaseAbstraction codebase, the Example models implement fragments in the models, while the ProviderQueryProvider class implements them in the query library.

The IQueryFragmentProvider interface specifies a single method that must be implemented, the Fragments method. The following class is an extension of the IParameterProvider example, demonstrating a model class that is also a fragment provider.

namespace DocExample.Models
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using DatabaseAbstraction.Interfaces;
    using DatabaseAbstraction.Utils;

    /// <summary>
    /// This class serves as a handy example
    /// </summary>
    public class Example : IParameterProvider, IQueryFragmentProvider
    {
        /// <summary>
        /// The ID of this example
        /// </summary>
        public int ID { get; set; }

        /// <summary>
        /// The first column for this example
        /// </summary>
        public string Column1 { get; set; }

        /// <summary>
        /// The second column in this example
        /// </summary>
        public bool Column2 { get; set; }

        /// <summary>
        /// The third column in this example
        /// </summary>
        public DateTime? Column3 { get; set; }

        /// <summary>
        /// Constructor (empty object)
        /// </summary>
        public Example() { }

        /// <summary>
        /// Constructor (filled object)
        /// </summary>
        /// <param name="reader">
        /// An open data reader, pointing to the row to use
        /// </param>
        public Example(IDataReader reader)
        {
            ID = reader.GetInt32(reader.GetOrdinal("example_id"));
            Column1 = reader.GetString(reader.GetOrdinal("column_1"));
            Column2 = reader.GetBoolean(reader.GetOrdinal("column_2"));
            Column3 = NullUtils.GetDateTimeOrNull(reader, "column_3");
        }

        /// <summary>
        /// Get the properties of this object as a parameter dictionary
        /// </summary>
        /// <returns>
        /// The properties of this object as a parameter dictionary
        /// </returns>
        public IDictionary<string, object> Parameters()
        {
            var parameters = new Dictionary<string, object>();

            parameters.Add("example_id", ID);
            parameters.Add("column_1", Column1);
            parameters.Add("column_2", Column2);
            parameters.Add("column_3", NullUtils.GetNullOrDateTime(Column3));

            return parameters;
        }

        /// <summary>
        /// Get the fragments provided by this class
        /// </summary>
        /// <param name="fragments">
        /// The fragment library being built
        /// </param>
        public void Fragments(IDictionary<string, QueryFragment> fragments)
        {
            fragments.Add("example.select", Select());
            fragments.Add("example.where.example_id", WhereExampleID());
        }

        /// <summary>
        /// example.select Fragment
        /// </summary>
        /// <returns>
        /// The query fragment
        /// </returns>
        private QueryFragment Select()
        {
            return new QueryFragment
            {
                SQL = @"SELECT
                        example_id, column_1, column_2, column_3
                    FROM example_table"
            };
        }

        /// <summary>
        /// example.where.example_id Fragment
        /// </summary>
        /// <returns>
        /// The query fragment
        /// </returns>
        private QueryFragment WhereExampleID()
        {
            var fragment = new QueryFragment { SQL = "WHERE example_id = @example_id" };
            fragment.Parameters.Add("example_id", DbType.Int32);

            return fragment;
        }
    }
}

A fragment can have SQL and parameters; these will be assembled when the master query library is filled.

<<

Last edited May 6, 2012 at 4:56 AM by danielsummers, version 4

Comments

No comments yet.