Thursday, March 09, 2006
As a follow-up to my previous post on creating a DataManager class for WilsonORMapper that uses the IsolatedContext, I'm posting a download that includes updates for Paul Welter's excellent CodeSmith templates for WilsonORMapper.  These templates are intended for use with Web projects.  The DataManager stores the IsolatedContext instance in the current HttpContext so that the same IsolatedContext is used throughout the current Request.

To use the new templates, just unzip the files in the /Internal folder where the existing DataManager templates are stored.

FYI, although I've confirmed that they compile, I have not tested the VB.NET and VB.NET 2.0 DataManager versions.  If you find any issues, I would appreciate your feedback.

Download the Templates

Thursday, March 09, 2006 11:01:13 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, February 22, 2006
In case someone else would like to know how to create a singleton DataManager class for WilsonORMapper that uses IsolatedContext and works in ASP.NET...

View DataManager.cs

using System.Configuration;
using System.IO;
using System.Reflection;
using System.Web;
using Wilson.ORMapper;

namespace Portal.Data
{
    /// <summary>
    /// The DataManager class is the singleton instance of the ObjectSpace class
    /// </summary>
    public sealed class DataManager
    {
        private const string MAPPING_FILE = "Mapping.config";
        private static readonly Guid CONTEXT_KEY = Guid.NewGuid();
        
        /// <summary>The application connection string read from app.config</summary>        
        /// <example>
        /// Add the following key to the "appSettings" section of your config:
        /// <code><![CDATA[
        ///     <configuration>
        ///            <appSettings>
        ///                <add key="IMI.Portal.Framework.Data.ConnectionString" value="Data Source=(local);Initial Catalog=DATABASE;User ID=USERNAME;Password=PASSWORD;" />
        ///            </appSettings>
        ///     </configuration>
        /// ]]></code>
        /// </example>
        public static readonly string ConnectionString = ConfigurationSettings.AppSettings["ConnectionString"];
        public static readonly string CurrentProvider = ConfigurationSettings.AppSettings["Provider"];

        /// <summary>The singletion instance of an ObjectSpace Class</summary>
        private static ObjectSpace objectSpace; // = GetDefaultInstance();
        private static object syncLock = new object();

        private DataManager()
        { }

        #region public static ObjectSpace ObjectSpace

        /// <summary>The singleton method for retrieving the global ObjectSpace</summary>
        public static ObjectSpace ObjectSpace
        {
            get
            {
                if (objectSpace == null)
                {
                    lock (syncLock)
                    {
                        if (objectSpace == null)
                        {
                            objectSpace = GetDefaultInstance();
                        }
                    }
                }
                
                HttpContext context = HttpContext.Current;
                if (context != null)
                {
                    ObjectSpace isolatedContext = (ObjectSpace) context.Items[CONTEXT_KEY];
                    if (isolatedContext == null)
                    {
                        // Cache the isolated context in the current request so that it is used
                        // throughout the entire request

                        isolatedContext = objectSpace.IsolatedContext;
                        context.Items[CONTEXT_KEY] = isolatedContext;
                    }
                    return isolatedContext;
                }
                else
                {
                    return objectSpace;
                }
            }
        }

        #endregion

        #region private static ObjectSpace GetDefaultInstance()

        private static ObjectSpace GetDefaultInstance()
        {
            Assembly assembly = Assembly.GetAssembly(typeof(DataManager));
            
            using (Stream mappingStream = assembly.GetManifestResourceStream(
                typeof(DataManager),
                MAPPING_FILE))
            {

                switch(CurrentProvider)
                {
                    case "MySQL":

                        return new ObjectSpace(
                            mappingStream,
                            ConnectionString,
                            GetMySQLProvider(),
                            20, 5);

                    case "PostgreSQL":

                        return new ObjectSpace(
                            mappingStream,
                            ConnectionString,
                            GetPostgreSQLProvider(),
                            20, 5);

                    // TODO: Oracle?

                    default:

                        return new ObjectSpace(
                            mappingStream,
                            ConnectionString,
                            Provider.MsSql,
                            20, 5);

                }
                
            }
        }

        #endregion

        #region private static CustomProvider GetMySQLProvider()

        private static CustomProvider GetMySQLProvider()
        {
            //Provider provider;
            CustomProvider provider;
            provider=new CustomProvider("MySql.Data", "MySql.Data.MySqlClient.MySqlConnection", "MySql.Data.MySqlClient.MySqlDataAdapter");
            provider.StartDelimiter="";
            provider.EndDelimiter="";
            provider.LineTerminator=";";
            provider.IdentityQuery= "SELECT LAST_INSERT_ID()";
            provider.SelectPageQuery="SELECT * LIMIT {0} OFFSET {1}";
            provider.ParameterPrefix = "?";
            provider.GuidDelimiter = "'";

            return provider;
            
        }

        #endregion

        #region private static CustomProvider GetPostgreSQLProvider()

        private static CustomProvider GetPostgreSQLProvider()
        {
            // Npgsql, the .NET provider for PostgreSQL can be found here:
            // http://pgfoundry.org/projects/npgsql

            CustomProvider provider;
            provider=new CustomProvider("Npgsql", "Npgsql.NpgsqlConnection", "Npgsql.NpgsqlDataAdapter");
            provider.StartDelimiter="[";
            provider.EndDelimiter="]";
            provider.LineTerminator=";";
            provider.IdentityQuery= "SELECT currval('{1}_{0}_seq')";
            provider.SelectPageQuery="SELECT * LIMIT {0} OFFSET {1}";
            provider.ParameterPrefix = ":";
            //not sure about this
            provider.GuidDelimiter = "'";

            return provider;
            
        }

        #endregion
    }
}
       
Wednesday, February 22, 2006 8:43:01 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, January 24, 2006
A minor release, but looks like some major improvements, such as a new SQL Server 2005 provider that takes advantage of some new features for better performance.

I've plugged Paul Wilson's O/R Mapper before, but I don't think it would hurt to reiterate that it is a fantastic tool.  I strongly encourage you to take it for a real test run (read: complete a small but real-world application with it).  Reading the feature list and taking it for a quick spin just won't do it justice.  If you've not used an O/R mapper before, it takes a little time to adopt the right mindset.  However, I think the benefits will become very clear once you see what it is capable of.  The beauty of WilsonORMapper is in its simplicity. 

I also recommend you try Paul Welter's CodeSmith templates for WilsonORMapper.  You can point CodeSmith at your database and generate a complete set of business classes ready to handle just about everything you need to do.  I have not yet tried the new CodeSmith templates from Jason Bunting.

Full list of changes can be found on Paul's blog.

Tuesday, January 24, 2006 11:23:32 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |