Click here to Skip to main content
15,886,067 members
Articles / Programming Languages / C#

Using a LLBLGen-generated data-access tier

Rate me:
Please Sign up or sign in to vote.
4.82/5 (18 votes)
24 Aug 2002BSD9 min read 323.4K   7.7K   109  
An article which describes how to use the data-access tier, generated by the free, open source data-access tier generator for .NET: LLBLGen. The sourcecode for LLBLGen v1.2 in C# is included, plus the generated data-access tier used in this article (C# and T-SQL) and the creation script for the data
//////////////////////////////////////////////////////////////////////
// Part of LLBLGen sourcecode. See version information
//////////////////////////////////////////////////////////////////////
// COPYRIGHTS:
// Copyright (c)2002 Solutions Design. All rights reserved.
// 
// Released under the following license: (BSD2)
// -------------------------------------------
// Redistribution and use in source and binary forms, with or without modification, 
// are permitted provided that the following conditions are met: 
//
// 1) Redistributions of source code must retain the above copyright notice, this list of 
//    conditions and the following disclaimer. 
// 2) Redistributions in binary form must reproduce the above copyright notice, this list of 
//    conditions and the following disclaimer in the documentation and/or other materials 
//    provided with the distribution. 
// 
// THIS SOFTWARE IS PROVIDED BY SOLUTIONS DESIGN ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOLUTIONS DESIGN OR CONTRIBUTORS BE LIABLE FOR 
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
//
// The views and conclusions contained in the software and documentation are those of the authors 
// and should not be interpreted as representing official policies, either expressed or implied, 
// of Solutions Design. 
//
//////////////////////////////////////////////////////////////////////
// Contributers to the code:
//		- Frans Bouma [FB]
//////////////////////////////////////////////////////////////////////
using System;
using System.Collections;

namespace LLBLGen
{

	/// <summary>
	/// Purpose: class that represents a tablefield. Used by clsTable to store fieldinformation
	/// </summary>
	/// <remarks>Implements the IComparable interface for the fieldsort based on type.</remarks>
	public class clsField : IComparable
	{
		#region Class Member Declarations
			string			m_sFieldName, m_sDataType, m_sDefaultValue;
			int				m_iOrdinalPosition, m_iLength, m_iPrecision, m_iScale;
			bool			m_bIsComputed, m_bIsIdentity, m_bIsRowGUIDColumn, m_bIsForeignKey, 
							m_bIsExcluded, m_bIsPrimaryKey, m_bIsNullable, m_bHasUniqueConstraint;
			SortedList		m_slTypeToPrefix, m_slTypeToNETType, m_slTypeToSqlType, m_slTypeToCSCastType,
							m_slTypeToVBCastType;
		#endregion

		/// <summary>
		/// Purpose: Constructor
		/// </summary>
		/// <param name="sFieldName">Name of field in table</param>
		public clsField(string sFieldName)
		{
			m_sFieldName = sFieldName;
		}


		/// <summary>
		/// Purpose: Implementation of the CompareTo method of the IComparable interface.
		/// </summary>
		/// <param name="oToCompareTo">Object of type clsField to compare the current instance with</param>
		/// <returns>-1 if this.sDataType is less than the sDataType of ofToCompare (stringcompare)
		/// 0, if this.sDataType is equal to ofToCompare.sDataType
		/// 1, if this.sDataType is greater than ofToCompare.sDataType </returns>
		public int CompareTo(Object oToCompareTo)
		{
			clsField ofToCompareTo = (clsField) oToCompareTo;
		
			if(ofToCompareTo.GetType() != this.GetType())
			{
				// throw exception
				throw new ArgumentException("clsField.CompareTo::object passed is not of the same type as 'clsField'");
			}
			if(this.GetFieldTypeAsNETType()==ofToCompareTo.GetFieldTypeAsNETType())
			{
				return 0;
			}
			return m_sDataType.CompareTo(ofToCompareTo.sDataType);
		}


		/// <summary>
		/// Purpose: returns the fieldname usable as T-SQL Variable, inclusive '@' and prefix if necessary
		/// </summary>
		/// <param name="bPrefixSPParams">Flag to prefix returned params with a type prefix (Hungarian Coding) (true) or not (false)</param>
		/// <returns>String representation of field, usable as T-SQL variable.</returns>
		/// <remarks>It replaces spaces in fieldnames with a '_'. It's unwise to use spaces in databasefields, but
		/// if you do, the tool will correctly handle these.</remarks>
		public string GetFieldAsTSQLParam(bool bPrefixSPParams)
		{
			if(bPrefixSPParams)
			{
				return "@" + m_slTypeToPrefix[m_sDataType].ToString() + m_sFieldName.Replace(" ","_");
			}
			else
			{
				return "@" + m_sFieldName.Replace(" ","_");
			}
		}


		/// <summary>
		/// Purpose: returns the type of the field as a T-SQL type, like varchar(lengthoffield).
		/// </summary>
		/// <returns>T-SQL version of the field's type</returns>
		public string GetFieldTypeAsTSQLType()
		{
			string	sToReturn;
			
			switch(m_sDataType)
			{
				case "bigint":
				case "bit":
				case "datetime":
				case "image":
				case "int":
				case "money":
				case "ntext":
				case "real":
				case "smalldatetime":
				case "smallint":
				case "smallmoney":
				case "sql_variant":
				case "sysname":
				case "text":
				case "timestamp":
				case "tinyint":
				case "uniqueidentifier":
					sToReturn = m_sDataType;
					break;
				case "binary":
				case "char":
				case "nchar":
				case "nvarchar":
				case "varbinary":
				case "varchar":
					sToReturn = m_sDataType + "(" + m_iLength + ")";
					break;
				case "decimal":
				case "numeric":
					sToReturn = m_sDataType + "(" + m_iPrecision + ", " + m_iScale + ")";
					break;
				case "float":
					sToReturn = m_sDataType + "(" + m_iPrecision + ")";
					break;
				default:
					sToReturn = "userdefined_type";
					break;
			}
			return sToReturn;
		}


		/// <summary>
		/// Purpose: returns the default value for the type of this field as a string. This
		/// default value is emitted to the Stored Procedure generators. The routine checks first if
		/// this field has a default value constraint, which value is stored in a membervariable. If
		/// not, a fieldtype specific string is constructed.
		/// </summary>
		/// <returns>The default value to emit in a stored procedure.</returns>
		/// <remarks>Used to supply update/insert queries with values for excluded fields.</remarks>
		public string GetDefaultSPValueAsString()
		{
			string sToReturn;
		
			if(m_sDefaultValue.Length > 0)
			{
				// has default value. Return that value
				return m_sDefaultValue;
			}
		
			// doesn't have a default constraint. Return a default value constructed
			// by ourselves.
			switch(m_sDataType)
			{
				case "int":
				case "smallint":
				case "tinyint":
				case "bigint":
				case "bit":
				case "binary":
				case "decimal":
				case "image":
				case "numeric":
				case "timestamp":
				case "varbinary":
					sToReturn = "0";
					break;
				case "varchar":
				case "char":
				case "nvarchar":
				case "nchar":
				case "text":
				case "ntext":
				case "sql_variant":
				case "sysname":
					sToReturn = "''";
					break;
				case "datetime":
				case "smalldatetime":
					sToReturn = "GETDATE()";
					break;
				case "float":
				case "real":
				case "money":
				case "smallmoney":
					sToReturn = "0.0";
					break;
				case "uniqueidentifier":
					sToReturn = "NEWID()";
					break;
				default:
					sToReturn = "NULL";
					break;
			}
			return sToReturn;
		}


		/// <summary>
		/// Purpose: returns true when the field requires a nullvalue check in the SqlParameter creation code, so the
		/// code emitters have to emit a Null value check.
		/// </summary>
		/// <returns>true if the field requires a nullvalue check, otherwise false. It will only return true when
		/// the field is nullable AND the field is of a type which requires a nullvalue check in the SqlParameter
		/// creation code.</returns>
		public bool CheckIfNullValueCheckIsNeeded()
		{
			bool		bToReturn;
		
			if(!m_bIsNullable)
			{
				// field is not nullable, a nullvalue check is redundant, since the property code already
				// contains a nullvalue check.
				return false;
			}
			switch(m_sDataType)
			{
				case "image":
				case "text":
				case "ntext":
					bToReturn = true;
					break;
				case "int":
				case "smallint":
				case "tinyint":
				case "bigint":
				case "bit":
				case "binary":
				case "decimal":
				case "sql_variant":
				case "sysname":
				case "datetime":
				case "smalldatetime":
				case "timestamp":
				case "float":
				case "real":
				case "money":
				case "smallmoney":
				case "uniqueidentifier":
				case "numeric":
				case "varchar":
				case "char":
				case "nvarchar":
				case "nchar":
				case "varbinary":
				default:
					bToReturn = false;
					break;
			}
			return bToReturn;
		}


		/// <summary>
		/// Purpose: returns the length value for this field. Most of the time this is a numeric value,
		/// but sometimes this is the length of a membervariable. 
		/// </summary>
		/// <param name="bStyleHungarian">Flag to use Hungarian Coding (true) or Microsoft caMel Style (false)</param>
		/// <returns>The length to emit in the parameter declaration.</returns>
		public string GetFieldLengthAsNETString(bool bStyleHungarian)
		{
			string sToReturn;
		
			switch(m_sDataType)
			{
				case "image":
					sToReturn = GetFieldAsNETParam(bStyleHungarian,true) + ".Length";
					break;
				case "text":
				case "ntext":
					sToReturn = GetFieldAsNETParam(bStyleHungarian,true) + ".Value.Length";
					break;
				case "int":
				case "smallint":
				case "tinyint":
				case "bigint":
				case "bit":
				case "binary":
				case "decimal":
				case "sql_variant":
				case "sysname":
				case "datetime":
				case "smalldatetime":
				case "timestamp":
				case "float":
				case "real":
				case "money":
				case "smallmoney":
				case "uniqueidentifier":
				case "numeric":
				case "varchar":
				case "char":
				case "nvarchar":
				case "nchar":
				case "varbinary":
				default:
					sToReturn = m_iLength.ToString();
					break;
			}
			return sToReturn;
		}


		/// <summary>
		/// Purpose: returns the length value for this field. Most of the time this is a numeric value,
		/// but sometimes this is the length of a membervariable. 
		/// </summary>
		/// <param name="bStyleHungarian">Flag to use Hungarian Coding (true) or Microsoft caMel Style (false)</param>
		/// <param name="bUseNullValueCheck">Flag to use the necessity of the Null value check. If true, 
		/// the length string for some fields is "[hungarianprefix][l/L]ength", which is a local variable generated
		/// into the code, which holds the actual length at runtime. This is necessary to avoid nullvalueexceptions
		/// when a NULL value is passed to [n]text fields and image fields, the length value of their SqlTypes object 
		/// is then not valid.</param>
		/// <returns>The length to emit in the parameter declaration.</returns>
		public string GetFieldLengthAsNETString(bool bStyleHungarian, bool bUseNullValueCheck)
		{
			string	sToReturn;
			bool	bNullValueCheckNecessary = CheckIfNullValueCheckIsNeeded();
		
			switch(m_sDataType)
			{
				case "image":
					if(bUseNullValueCheck && bNullValueCheckNecessary)
					{
						sToReturn = PrefixMethodParameter("Length", "i", bStyleHungarian);
					}
					else
					{
						sToReturn = GetFieldAsNETParam(bStyleHungarian,true) + ".Length";
					}
					break;
				case "text":
				case "ntext":
					if(bUseNullValueCheck && bNullValueCheckNecessary)
					{
						sToReturn = PrefixMethodParameter("Length", "i", bStyleHungarian);
					}
					else
					{
						sToReturn = GetFieldAsNETParam(bStyleHungarian,true) + ".Value.Length";
					}
					break;
				case "int":
				case "smallint":
				case "tinyint":
				case "bigint":
				case "bit":
				case "binary":
				case "decimal":
				case "sql_variant":
				case "sysname":
				case "datetime":
				case "smalldatetime":
				case "timestamp":
				case "float":
				case "real":
				case "money":
				case "smallmoney":
				case "uniqueidentifier":
				case "numeric":
				case "varchar":
				case "char":
				case "nvarchar":
				case "nchar":
				case "varbinary":
				default:
					sToReturn = m_iLength.ToString();
					break;
			}
			return sToReturn;
		}


		/// <summary>
		/// Purpose: returns the type of the field as a .NET type, like 'SqlDecimal'.
		/// </summary>
		/// <returns>C# version of the field's type</returns>
		public string GetFieldTypeAsNETType()
		{
			return  m_slTypeToNETType[m_sDataType].ToString();
		}


		/// <summary>
		/// Purpose: returns the type of the field as a C# cast type, like 'Decimal'.
		/// </summary>
		/// <returns>C# version of the field's cast type</returns>
		public string GetFieldTypeAsCSCastType()
		{
			return  m_slTypeToCSCastType[m_sDataType].ToString();
		}
		

		/// <summary>
		/// Purpose: returns the type of the field as a VB cast type, like 'Decimal'.
		/// Use this routine with CType(,)
		/// </summary>
		/// <returns>C# version of the field's cast type</returns>
		public string GetFieldTypeAsVBCastType()
		{
			return  m_slTypeToVBCastType[m_sDataType].ToString();
		}

		
		/// <summary>
		/// Purpose: returns the type of the field as an SqlType type, like 'Decimal'.
		/// </summary>
		/// <returns>SqlType version of the field's type</returns>
		public string GetFieldTypeAsSqlType()
		{
			return  m_slTypeToSqlType[m_sDataType].ToString();
		}
		

		/// <summary>
		/// Purpose: returns the fieldname usable as .NET Variable, inclusive 'm_' and prefix if necessary
		/// </summary>
		/// <param name="bStyleHungarian">Flag to use Hungarian Coding (true) or Microsoft caMel Style (false)</param>
		/// <param name="bIsMember">Flag to prefix returned params with a 'm_' or '_', so it's a membervariable.</param>
		/// <returns>String representation of field, usable as NET variable.</returns>
		/// <remarks>It replaces spaces in fieldnames with a '_'. It's unwise to use spaces in databasefields, but
		/// if you do, the tool will correctly handle these.</remarks>
		public string GetFieldAsNETParam(bool bStyleHungarian, bool bIsMember)
		{
			string	sFieldName=m_sFieldName.Replace(" ","_");
			string	sPrefix;
		
			if(bIsMember)
			{
				if(bStyleHungarian)
				{
					sPrefix = "m_";
				}
				else
				{
					sPrefix = "_";
				}
			}
			else
			{
				sPrefix="";
			}
			if(bStyleHungarian)
			{
				return sPrefix + m_slTypeToPrefix[m_sDataType].ToString() + 
					sFieldName.Substring(0,1).ToUpper() + sFieldName.Substring(1, sFieldName.Length-1);
			}
			else
			{
				return sPrefix + sFieldName.Substring(0,1).ToLower() + sFieldName.Substring(1, sFieldName.Length-1);
			}
		}
		

		/// <summary>
		/// Purpose: returns the fieldname usable as .NET Property, inclusive prefix if necessary
		/// </summary>
		/// <param name="bPrefixProperties">Flag to prefix properties using Hungarian Coding (true) or just 
		/// use Microsoft caMel Style names (false)</param>
		/// <returns>String representation of field, usable as .NET Property.</returns>
		/// <remarks>It replaces spaces in fieldnames with a '_'. It's unwise to use spaces in databasefields, but
		/// if you do, the tool will correctly handle these.</remarks>
		public string GetFieldAsNETProperty(bool bPrefixProperties)
		{
			string	sFieldName=m_sFieldName.Replace(" ","_");
			
			if(bPrefixProperties)
			{
				return m_slTypeToPrefix[m_sDataType].ToString() + 
					sFieldName.Substring(0,1).ToUpper() + sFieldName.Substring(1, sFieldName.Length-1);
			}
			else
			{
				return sFieldName.Substring(0,1).ToUpper() + sFieldName.Substring(1, sFieldName.Length-1);
			}
		}


		/// <summary>
		/// Purpose: prefixes the given method parameter according to the settings set.
		/// </summary>
		/// <param name="sParameterName">Name of the method parameter to prefix</param>
		/// <param name="sTypePrefix">Type prefix to add as a prefix if method parameters should be prefixed</param>
		/// <param name="bStyleHungarian">Flag if hungarian coding should be used (true) or not (false)</param>
		/// <returns>Name of method parameter according to the settings set</returns>
		private string PrefixMethodParameter(string sParameterName, string sTypePrefix, bool bStyleHungarian)
		{
			if(bStyleHungarian)
			{
				return sTypePrefix + sParameterName;
			}
			else
			{
				return sParameterName.Substring(0,1).ToLower() + sParameterName.Substring(1,sParameterName.Length-1);
			}
		}


		#region Class Property Declarations
		public string sFieldName
		{
			get	{ return m_sFieldName; }
		}
		public bool bIsExcluded
		{
			get	{ return m_bIsExcluded;	}
			set	{ m_bIsExcluded = value; }
		}
		public SortedList slTypeToPrefix
		{
			set	{ m_slTypeToPrefix=value; }
		}
		public SortedList slTypeToNETType
		{
			set { m_slTypeToNETType=value; }
		}
		public SortedList slTypeToCSCastType
		{
			set { m_slTypeToCSCastType=value; }
		}
		public SortedList slTypeToVBCastType
		{
			set { m_slTypeToVBCastType=value; }
		}
		public SortedList slTypeToSqlType
		{
			set	{ m_slTypeToSqlType=value; }
		}
		public string sDataType
		{
			get	{ return m_sDataType; }
			set	{ m_sDataType = value; }
		}
		public int iOrdinalPosition
		{
			get	{ return m_iOrdinalPosition; }
			set	{ m_iOrdinalPosition = value; }
		}
		public int iLength
		{
			get	{ return m_iLength; }
			set	{ m_iLength = value; }
		}
		public int iPrecision
		{
			get	
			{ 
				//////////////
				// .NET v1.0 BUG WORKAROUND: Precision can't be > 38. SQLServer 's float has
				// a precision 53. We have to cap the precision to 38, until MS fixes this
				// bug
				/////////////
				if(m_iPrecision>38)
				{
					return 38;
				}
				else
				{
					return m_iPrecision; 
				}
			}
			set	{ m_iPrecision = value; }
		}
		public int iScale
		{
			get	{ return m_iScale; }
			set	{ m_iScale = value; }
		}
		public bool bIsComputed
		{
			get	{ return m_bIsComputed; }
			set	{ m_bIsComputed = value; }
		}
		public bool bIsIdentity
		{
			get	{ return m_bIsIdentity; }
			set	{ m_bIsIdentity = value; }
		}
		public bool bIsRowGUIDColumn
		{
			get	{ return m_bIsRowGUIDColumn; }
			set	{ m_bIsRowGUIDColumn = value; }
		}
		public bool bIsForeignKey
		{
			get	{ return m_bIsForeignKey; }
			set	{ m_bIsForeignKey = value; }
		}
		public bool bIsPrimaryKey
		{
			get { return m_bIsPrimaryKey; }
			set	{ m_bIsPrimaryKey = value; }
		}
		public bool bIsNullable
		{
			get	{ return m_bIsNullable; }
			set { m_bIsNullable = value; }
		}
		public bool bHasUniqueConstraint
		{
			get { return m_bHasUniqueConstraint; }
			set { m_bHasUniqueConstraint = value; }
		}
		public bool bIsTimeStamp
		{
			get { return (m_sDataType.ToLower() == "timestamp"); }
		}
		public string sDefaultValue
		{
			get { return m_sDefaultValue; }
			set { m_sDefaultValue = value; }
		}
		#endregion
	}
}

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 BSD License


Written By
Web Developer
Netherlands Netherlands
Senior Software Engineer @ Solutions Design, a company for internet- and intranet applications, based in The Hague, Netherlands. B.Sc. in Computer Science.

Developer of LLBLGen and LLBLGen Pro. http://www.llblgen.com

Comments and Discussions