Click here to Skip to main content
Licence CPOL
First Posted 15 Apr 2008
Views 7,705
Downloads 59
Bookmarked 8 times

My Own Version of nHybernate

By | 15 Apr 2008 | Article
An article on reflection, attributes and database manipulation with a touch of 3tier architectural design pattern

Introduction

This article demonstrates the general programming methodology for enterprise applications while talking about attributes and reflection. I will create a set of attribute classes, implement them and then I will create a class that will use the attributes set in another class and manipulate a database table.

Background

For me, the most interesting part of programming is how things work. I have always wondered why NHybernate is so mapping-dependent until I was told (not confirmed) that it also uses attributes. I was also made aware of the fact that LINQ uses attributes. That was rather exciting so I went ahead to write my own implementation and found it very useable on some of my personal projects. Now, I want to share it with you.

Using the Code

The Basis for the Attribute class is something like this:

    /// <summary>
    /// Attribute definition for a table (used only at class level)
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class TableAttribute : System.Attribute
    {
        private string _TableName;

        /// <summary>

        /// Constructor
        /// </summary>
        /// <param name="tableName">The table name</param>
        public TableAttribute(string tableName)
            : base()
        {
            _TableName = tableName;
        }

        /// <summary>
        /// Specify the name of the table for use in PPDataCore
        /// </summary>
        public string TableName
        {
            get
            {
                return _TableName;
            }
            set
            {
                _TableName = value;
            }
        }
    }

It defines an attribute class that will be used by a DTO class (e.g User, which defines the table it maps to).

I also have the ColumnAttribute class:

    /// <summary>
    /// Attribute definition for a column (used only at property level)
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
    public class ColumnAttribute : System.Attribute
    {
        private string _ColumnName;
        private string _ColumnType;
        private KeyType _Key;

        /// <summary>
        /// Constructor
        /// </summary>

        /// <param name="columnName">Column name</param>
        /// <param name="columnType">Column type</param>
        /// <param name="key">key type (if key column)</param>
        public ColumnAttribute(string columnName, string columnType, KeyType key)
            : base()
        {
            _ColumnName = columnName;
            _ColumnType = columnType;
            _Key = key;
        }

        /// <summary>
        /// Column name
        /// </summary>

        public string ColumnName
        {
            get
            {
                return _ColumnName;
            }
            set
            {
                _ColumnName = value;
            }
        }

        /// <summary>
        /// Column type
        /// </summary>
        public string ColumnType
        {
            get
            {
                return _ColumnType;
            }
            set
            {
                _ColumnType = value;
            }
        }

        /// <summary>
        /// Key type (if key column)
        /// </summary>
        public KeyType Key
        {
            get
            {
                return _Key;
            }
            set
            {
                _Key = value;
            }
        }
    }

This defines some attributes that will be used to map the properties of the User class to the columns of the User table.

We can now go ahead and implement the Attributes class in our User class.

    [Table("Users")]
    public class User
    {
        private int _ID;
        private string _UserName;
        private string _FirstName;
        private string _LastName;
        private DateTime _BirthDate;

        [Column("ID", "System.Int32", KeyType.AutoGenerate)]
        public int ID
        {
            get
            {
                return _ID;
            }
            set
            {
                _ID = value;
            }
        }

        [Column("UserName", "System.String", KeyType.None)]
        public string UserName
        {
            get
            {
                return _UserName;
            }
            set
            {
                _UserName = value;
            }
        }

All these have to be dealth with, of course, and that is done right here:

        private List<ColumnDef> list;
        string TableName = "";
        private string keyColum;
        private string _QueryString;
        private object _CurrentObject;
        private Type _ObjectType;

        /// <summary>
        /// Bulk of the work is done here
        /// </summary>
        /// <param name="obj">The object instance to manipulate (if any), specify
        /// null if none</param>
        /// <param name="qType">The type of the object to be manipulated</param>

        private void GenerateTableManipStrings(object obj, QueryType qType)
        {
            _CurrentObject = obj;

            if (_CurrentObject != null && _CurrentObject.GetType() != _ObjectType)
            {
                return;
            }

            ColumnDef col = new ColumnDef();

            list = new List<ColumnDef>();
            
            _QueryString = "";
            keyColum = "";

            obj = _ObjectType.GetCustomAttributes(typeof(TableAttribute), false);
            Array attsT = (Array)obj;
            if (attsT.Length == 0)
            {
                TableName = _ObjectType.Name;
            }
            else
            {
                TableName = ((TableAttribute)attsT.GetValue(0)).TableName;
            }
            PropertyInfo[] props = _ObjectType.GetProperties();
            foreach (PropertyInfo prop in props)
            {
                try
                {
                    if (_CurrentObject != null)
                    {
                        col.Value = prop.GetValue(_CurrentObject, null);
                    }

                    object p = prop.GetCustomAttributes(typeof(ColumnAttribute), false);
                    Array attsC = (Array)p;
                    if (attsC.Length == 0)
                    {
                        col.Name = prop.Name;
                        col.Parameter = "@" + prop.Name;
                        col.Type = prop.PropertyType.ToString();
                    }
                    else
                    {
                        ColumnAttribute cAtt = (ColumnAttribute)attsC.GetValue(0);
                        col.Name = cAtt.ColumnName;
                        col.Parameter = "@" + cAtt.ColumnName;
                        col.Type = cAtt.ColumnType;
                        col.Key = cAtt.Key;
                        if ((cAtt.Key == KeyType.Primary || cAtt.Key ==
                            KeyType.AutoGenerate) && keyColum == "")
                        {
                            keyColum = cAtt.ColumnName;
                        }
                        else if ((cAtt.Key == KeyType.Primary || cAtt.Key ==
                            KeyType.AutoGenerate) && keyColum != "")
                        {
                            throw new Exception("Contains multiple key columns");
                        }
                    }
                    list.Add(col);
                }
                catch (Exception exp)
                {
                    throw exp;
                }
            }
        }

Points of Interest

Well that's about it. You can see that with Reflection, you can achieve just about anything in the world (literally). You can download the full source code project at the top.

History

This is the First Post - 14th April, 2008

License

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

About the Author

Member 3153651

Web Developer

Nigeria Nigeria

Member

A Computer Science graduate of Nnamdi Azikiwe University, Awka, Nigeria. Started programming with VB6 in 2002. Moved on to C++ Later that year and then Java.
 
Entered the .NET platform 2005 (C# and VB.NET) and has worked as a developer and support personnel in various organizations including a software firm, a HMO and a Bank.
 
Key interest areas include graphics, windows development, web development and systems administration.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 15 Apr 2008
Article Copyright 2008 by Member 3153651
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid