Click here to Skip to main content
15,885,890 members
Articles / Programming Languages / SQL

Abstract Data Access Layer Design

Rate me:
Please Sign up or sign in to vote.
4.85/5 (16 votes)
5 Sep 2009CPOL4 min read 72.9K   1.2K   68  
The present document tries to describe the architecture of a specific layer of access to data for relational databases. This document tries to present/display a form to automate tasks of access to data.
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Reflection;
using XPeriment.DataAccessTasks;

namespace XPeriment.Persistence.PersistentObjects
{
    public class ObjectMapping
    {
        private string typename = "";
        private string targettable = "";

        private Dictionary<string, FieldMapping> propertymappings = new Dictionary<string, FieldMapping>();
        private Dictionary<string, FieldMapping> databasemappings = new Dictionary<string, FieldMapping>();

        internal string TypeName
        {
            get
            {
                return typename;
            }
            set
            {
                typename = value;
            }
        }

        internal string TargetTable
        {
            get
            {
                return targettable;
            }
            set
            {
                targettable = value;
            }
        }

        internal string this[string source, MappingDirectionTypes direction]
        {
            get
            {
                if (direction == MappingDirectionTypes.LoadDirection)
                    return databasemappings[source].PropertyName;
                if (direction == MappingDirectionTypes.SaveDirection)
                    return propertymappings[source].DatabaseField;
                throw new Exception("Source property or field name not found on persistence catalog.");
            }
        }

        internal void AddMapping(string propertyName, string databaseFieldName)
        {
            FieldMapping m = new FieldMapping(propertyName, databaseFieldName);
            propertymappings.Add(m.PropertyName, m);
            databasemappings.Add(m.DatabaseField, m);
        }

        internal void AddMapping(string propertyName, string databaseFieldName, bool isPrimaryKey, bool nullsAllowed)
        {
            FieldMapping m = new FieldMapping(propertyName, databaseFieldName, isPrimaryKey);
            m.NullsAllowed = nullsAllowed;
            propertymappings.Add(m.PropertyName, m);
            databasemappings.Add(m.DatabaseField, m);
        }

        internal void AddMapping(string propertyName, string databaseFieldName, bool isPrimaryKey, bool nullsAllowed, bool isFk)
        {
            FieldMapping m = new FieldMapping(propertyName, databaseFieldName, isPrimaryKey);
            m.IsForaignKey = isFk;
            m.NullsAllowed = nullsAllowed;
            propertymappings.Add(m.PropertyName, m);
            databasemappings.Add(m.DatabaseField, m);
        }

        internal string GetFieldName(string propertyName)
        {
            if(propertymappings.ContainsKey(propertyName))
                return propertymappings[propertyName].DatabaseField;
            return null;
        }

        internal string GetPropertyName(string fielName)
        {
            return databasemappings[fielName].PropertyName;
        }

        internal Dictionary<string, object> GetFieldValues(object obj)
        {
            Dictionary<string, object> retval = new Dictionary<string, object>();
            Type objtype = obj.GetType();
            PropertyInfo[] props = objtype.GetProperties();
            foreach (PropertyInfo pi in props)
            {
                if (!ReflectionUtility.MarkedAsIgnoreMapping(pi))
                {
                    if (!ReflectionUtility.MarkedAsPrimaryKey(pi))
                    {
                        if (!ReflectionUtility.MarkedAsForaignKey(pi))
                        {
                            string dbfield = GetFieldName(pi.Name);
                            if (dbfield != null)
                                retval.Add(dbfield, pi.GetValue(obj, null));
                        }
                        else
                        {
                            string dbfield = GetFieldName(pi.Name);
                            if (dbfield != null)
                            {
                                PersistentObject po = (PersistentObject)pi.GetValue(obj, null);
                                ObjectMapping childmap = PersistenceCatalog.GetTypeMapping(po.GetType());
                                retval.Add(dbfield, childmap.GetPrimaryKeyValue(po));
                            }
                        }
                    }
                }
            }
            return retval;
        }

        private object GetPrimaryKeyValue(object obj)
        {
            Type objType = obj.GetType();
            foreach (string key in propertymappings.Keys)
            {
                PropertyInfo pi = objType.GetProperty(key);
                if (propertymappings.ContainsKey(pi.Name))
                    if (propertymappings[key].IsPrimaryKey)
                        return pi.GetValue(obj, null);
            }
            throw new Exception("Not primary key defined for type " + obj.GetType().ToString());
        }

        internal List<PersistentObject> GetChildPersistentObjects(object obj)
        {
            List<PersistentObject> retval = new List<PersistentObject>();
            foreach (FieldMapping fd in propertymappings.Values)
                if (fd.IsForaignKey)
                    retval.Add(obj.GetType().GetProperty(fd.PropertyName).GetValue(obj, null) as PersistentObject);
            return retval;
        }

        internal Dictionary<string, object> GetForaignKeyFalues(object obj)
        {
            Dictionary<string, object> retval = new Dictionary<string, object>();

            return retval;
        }

        internal string GetPrimaryKeysFilter(object obj)
        {
            string retval = "";
            Type objType = obj.GetType();
            int counter = 0;
            foreach (FieldMapping map in databasemappings.Values)
            {
                if (map.IsPrimaryKey)
                {
                    counter++;
                    object fieldvalue = objType.GetProperty(map.PropertyName).GetValue(obj, null);
                    if (retval.Length > 0)
                        retval += " AND ";
                    retval +=  map.DatabaseField + " = " + new ScriptBuilder().FormatValue(fieldvalue) + "";
                }
            }
            return retval;
        }

        internal void SetPropertyValues(object obj, DataRow sourceRow)
        {
            foreach (string key in propertymappings.Keys)
            {
                Type objType = obj.GetType();
                PropertyInfo pi = objType.GetProperty(key);
                if (propertymappings.ContainsKey(pi.Name))
                {
                    if(pi.PropertyType.IsPrimitive || pi.PropertyType == typeof(string))
                        pi.SetValue(obj, sourceRow[propertymappings[key].DatabaseField], null);
                    if (pi.PropertyType.IsSubclassOf(typeof(PersistentObject)))
                    {
                        PersistentObject po = (PersistentObject) pi.GetValue(obj, null);
                        po.Load(sourceRow[propertymappings[key].DatabaseField]);
                    }
                }
            }
        }


        internal void SetPrimaryKeyValue(object obj, object pkValue)
        {
            Type objType = obj.GetType();
            foreach (string key in propertymappings.Keys)
            {
                PropertyInfo pi = objType.GetProperty(key);
                if (propertymappings.ContainsKey(pi.Name))
                    if(propertymappings[key].IsPrimaryKey)
                        pi.SetValue(obj, Convert.ToInt32(pkValue), null);
            }

        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems Engineer
Colombia Colombia
http://www.construirsoftware.blogspot.com/

Comments and Discussions