Login Skip Navigation LinksWilsonORMapper > Forums Search
Demo Version Demo Version
Download and try for yourself a fully working demo version, including sample apps and documentation.  The only limitation is that the demo version only works inside the debugger.

PayPal Subscribe
Get It All for $50 USD:
WebPortal, ORMapper,
Source Code, All Updates
PayPal

User Login User Login
Log In
 
 
Reset Password

Wilson ORMapper Forums Wilson ORMapper Forums : Templates & More : Templates for ASP.NET environment???

Date Post
2/22/2006 11:45:46 AM Anyone have any mygeneration or codesmith templates for building objects and the mapping.xml that allow you to plug in an IsolatedContext object created by the asp.net application? I've played around with the CodeSmith templates that you can get from the site ... I like the API ... but they don't seem very usable outside winform apps.

thanks - Wayde
2/22/2006 7:00:39 PM I've got a DataManager class I use in ASP.NET that uses IsolatedContext. I've posted a sample file on my web site at

http://www.christianasp.net/downloads/DataManager.cs.txt

I haven't incorporated the changes back into a CodeSmith template. The DataManager class should never change, so it's not hard to just take one that's already working and copy it to another project.

Best regards,
David Neal
2/23/2006 11:21:17 AM Hey David,

Perfect timing! I was just tacking this issue and I saw your blog post on this. Just what I was looking for. Great work.

Regards,
Jason Shigley
2/23/2006 3:38:47 PM Jason,

Nice clean class... I like your extensions for grabbing the provider from the configuration, I'll be adding that to mine :)

One suggestion is to not use a literal string as the key into the Context/Cache. Rather, you would be much better off using a Guid like this:

static readonly Guid CONTEXT_KEY = Guid.NewGuid();

Here's my (simple version) Manager.cs, which spins up an IsolatedContext for each web request and has hooks for doing log4net logging.

public class Manager : IInterceptCommand
{
// Create log instance
private static readonly ILog log = LogManager.GetLogger("YOURAPP");

static readonly Guid contextKey = Guid.NewGuid();
static readonly object lockToken = new object();
static readonly Manager instance = new Manager();

private ObjectSpace orManager;

static public ObjectSpace ObjectSpace
{
get
{
// if running with a context available...
HttpContext myContext = HttpContext.Current;

if (myContext != null)
{
ObjectSpace currentSpace = myContext.Items[contextKey] as ObjectSpace;

if (currentSpace == null)
{
lock (lockToken)
{
// double-check lock
currentSpace = myContext.Items[contextKey] as ObjectSpace;

if (currentSpace == null)
{
currentSpace = instance.orManager.IsolatedContext;
myContext.Items[contextKey] = currentSpace;
}
}
}

return currentSpace;
}

return instance.orManager;
}
}

private Manager()
{
string connectionString = ConfigurationManager.ConnectionStrings["YOURAPP"].ConnectionString;
string orMappings = ConfigurationManager.AppSettings["ORMappings"];
string uiMappings = ConfigurationManager.AppSettings["UIMappings"];

this.orManager = new ObjectSpace(orMappings, connectionString, Provider.Sql2005, 0, 0);
this.orManager.SetInterceptor(this);
}

public void InterceptCommand(Guid transactionId, Type entityType, CommandInfo commandInfo, IDbCommand dbCommand)
{
if (log.IsTraceEnabled)
{
ThreadContext.Properties["TransactionId"] = transactionId;
ThreadContext.Properties["EntityType"] = entityType;
ThreadContext.Properties["CommandInfo"] = commandInfo;

log.Trace(new ORMapperIntercept(dbCommand, commandInfo));
}
}
}

public class ORMapperIntercept
{
IDbCommand dbCommand;
CommandInfo commandInfo;

string humanReadable;
static private readonly char[] lineEnds = new char[] { '\r', '\n' };

public ORMapperIntercept(IDbCommand dbCommand, CommandInfo commandInfo)
{
this.dbCommand = dbCommand;
this.commandInfo = commandInfo;
this.humanReadable = null;
}

public override string ToString()
{
if (humanReadable == null)
{
StringBuilder message = new StringBuilder();
message.Append(commandInfo.ToString());

if (dbCommand != null)
{
message.Append(": ")
.Append(dbCommand.CommandText.TrimEnd(lineEnds))
.Append("\r\n ");

for (int index = 0; index < dbCommand.Parameters.Count; index++)
{
IDbDataParameter parameter = dbCommand.Parameters[index] as IDbDataParameter;
message.Append(parameter.ParameterName)
.Append(" = ")
.Append(parameter.Value)
.Append(", ");
}

message.Length -= 2;
}

this.humanReadable = message.ToString();
}

return this.humanReadable;
}
}

Marc
2/24/2006 7:46:24 AM Marc,

Actually, I was complimenting David on his code :o) I had nothing to do with it other than it saving me some time.

Regards,
Jason
2/25/2006 7:30:33 PM Marc,

Thanks for the suggestion. I hadn't thought of using a Guid for that. Very cool!

David
3/1/2006 8:31:20 AM Why are you guys using a GUID for the context key name? Why not just use a string like "ORMapperIsolatedContext"? What's the advantage of a GUID?
3/1/2006 12:50:34 PM Have to say I didn't see any advantage to that approach myself, seeing as how it's a static readonly field. But different strokes for different folks.

Regards,
Jason
3/1/2006 2:39:56 PM They're trying to avoid any naming collisions -- not a bad idea if you don't control everything, although a little bizarre looking if you do control everything.

Thanks, Paul Wilson
3/1/2006 2:40:17 PM If there are two manager classes that have the same string as the cache key, they can conflict... nobody's gonna generate the same GUID -- that's why it's a Globally Unique IDentifier ;)

So this keeps your newly added assembly (which copied the template using "ORMapperIsolatedContext") from conflicting with MY assembly. This is important because we probably loaded two VERY DIFFERENT mapping files.
3/2/2006 6:02:12 AM In my case, we have a "portal framework" class library that has all the standard features of a web application, such as users, roles, security, content management, navigation, URL rewriting, file management, and so forth. This class library gets its own DataManager class, mapping.config, and set of entities. On top of this application framework we have built several web applications that have a separate DataManager class, entity classes, and a mapping.config that only includes the additional tables that are specific to that application. By using a Guid for the context key, I'll never have to worry about changing the key name whenever I set up a new project. Like Marc, I like to avoid "magical" numbers or strings hard-coded into my applications whenever possible.

As Forrest Gump said, "One less thing." ;)

David
3/2/2006 9:09:43 AM Note that you would have to be using two different managers IN THE SAME REQUEST to see a conflict. Just two different managers somewhere on a server are not going to see any conflicts. But for using two different instances of a mapper in the same request you would indeed have to have different cache keys.