Click here to Skip to main content
15,886,258 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.Reflection;
using System.Xml;
using System.IO;

namespace XPeriment.Persistence.PersistentObjects
{
    public static class PersistenceCatalog
    {
        private static Dictionary<Type, ObjectMapping> mappings = new Dictionary<Type, ObjectMapping>();

        private static string GetMappingFile(Type type)
        {
            object[] attributes = type.GetCustomAttributes(typeof(MappingFileAttribute), true);
            if (attributes.Length == 0)
                return null;
            MappingFileAttribute mapfileattrib = (MappingFileAttribute)attributes[0];
            return mapfileattrib.FileName;
        }

        private static bool IsTypeMappingDefined(Type type)
        {
            return mappings.ContainsKey(type);
        }

        private static void AddMappingForType(Type type, ObjectMapping newMapping)
        {
            if (mappings.ContainsKey(type))
                mappings.Remove(type);
            mappings.Add(type, newMapping);
        }

        private static void LoadMappingFromFile(string fileName)
        {
            XmlDocument document = new XmlDocument();
            try
            {
                document.Load(fileName);
            }
            catch
            {
                throw new Exception("Mappint file not found or invalid XML definition.");
            }
            XmlNodeList nodes = document.GetElementsByTagName("typemapping");
            if (nodes.Count == 0)
                throw new Exception("Mapping file is empty");
            ObjectMapping typemapping = new ObjectMapping();
            foreach (XmlNode node in nodes)
            {
                string typename = node.Attributes["typename"].Value;
                string tablename = node.Attributes["table"].Value;
                string assembly = node.Attributes["assembly"].Value;
                typemapping.TypeName = typename;
                typemapping.TargetTable = tablename;
                XmlNodeList mappingslist = node.ChildNodes;
                foreach (XmlNode mapppingnode in mappingslist)
                {
                    string propertyname = mapppingnode.Attributes["property"].Value;
                    string fieldname = mapppingnode.Attributes["field"].Value;
                    bool nullsallowed = bool.Parse(mapppingnode.Attributes["nullsallowed"].Value);
                    bool isprimarykey = bool.Parse(mapppingnode.Attributes["isprimarykey"].Value);
                    typemapping.AddMapping(propertyname, fieldname, isprimarykey, nullsallowed);
                }
                mappings.Add(Assembly.LoadFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, assembly)).GetType(typename) , typemapping);
            }
        }

        private static void LoadMappingFromType(Type type)
        {
            ObjectMapping newmapping = new ObjectMapping();

            MapToAttribute[] attribs = (MapToAttribute[])type.GetCustomAttributes(typeof(MapToAttribute), true);
            if (attribs.Length == 0)
                newmapping.TargetTable = type.Name;
            else
                newmapping.TargetTable = attribs[0].DBReference;
            PropertyInfo[] properties = type.GetProperties();
            foreach (PropertyInfo pi in properties)
            {
                if (!ReflectionUtility.MarkedAsIgnoreMapping(pi))
                {
                    Type propertyType = pi.PropertyType;
                    if (propertyType.IsGenericType && propertyType.Name.Contains("Nullable"))
                        propertyType = Nullable.GetUnderlyingType(propertyType);
                    if (propertyType.IsSubclassOf(typeof(PersistentObject)) || propertyType.IsPrimitive || propertyType == typeof(string))
                    {
                        string dbfield = ReflectionUtility.GetDBField(pi);
                        bool ispk = ReflectionUtility.MarkedAsPrimaryKey(pi);
                        bool nullsallowed = ReflectionUtility.IsNulable(pi);
                        bool isfk = ReflectionUtility.MarkedAsForaignKey(pi);
                        newmapping.AddMapping(pi.Name, dbfield, ispk, nullsallowed, isfk);
                    }
                }
            }
            mappings.Add(type, newmapping);
        }

        public static void LoadMapping(Type type)
        {
            if (!IsTypeMappingDefined(type))
            {
                string mappingfilename = GetMappingFile(type);
                if (mappingfilename != null)
                    LoadMappingFromFile(mappingfilename);
                else
                    LoadMappingFromType(type);
            }
        }

        public static ObjectMapping GetTypeMapping(Type type)
        {
            LoadMapping(type);
            return mappings[type];
        }

    }
}

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