Hi Kenneth,
In your case it seems like the same wrapping strategy will not work but you can use an AOP based solution to achieve your goal.
As background, Spring.NET has a base class (as in the Java version) DelegatingDbProvider, with some subclasses that allow for the user name and password to be set on a per-request basis or to pick a completely different database instance. See here for some details. These implementations essentially modify the connection string before the connection is open.
If you wrote a wrapper class that would execute the 'alter session' statements after creating the connection in an custom IDbProvider implementation. This would require opening the connection and associating and IDbCommand with a transaction. However, this would happen too soon as the IPlatformTransactionManager implementation hasn't created the connection/transaction pair yet.
The approach to use is to create an AOP interceptor that will be called right after the transaction interceptor. It can retrieve the current connection/transaction pair that is bound to thread local storage and then execute the 'alter select' command.
The Transactions QuickStart example shows how to chain interceptors where the pointcut is the [Transaction] attribute in the config file aspects-config.xml
This will essentially looks like the following
Code:
<object id="alterSessionInterceptor" type="MyNamespace.AlterSessionInterceptor">
<property name="DbProvider" ref="dbProvider"/>
</object>
<object id="txAttributePointcut" type="Spring.Aop.Support.AttributeMatchMethodPointcut, Spring.Aop">
<property name="Attribute" value="Spring.Transaction.Interceptor.TransactionAttribute, Spring.Data"/>
</object>
<aop:config>
<aop:advisor order="2"
advice-ref="alterSessionAdvice"
pointcut-ref="txAttributePointcut"/>
</aop:config>
and you need to add the following order statement for declarative transaction management
Code:
<tx:attribute-driven order="1"/>
The ordering will then be
- Transaction interceptor
- Alter session interceptor
The implementation of the AlterSessionInterceptor would roughly be
Code:
public sealed class AlterSelectInterceptor : AdoDaoSupport, IMethodBeforeAdvice
{
public virtual void Before(MethodInfo method, object[] args, object target)
{
AdoTemplate.ExecuteNonQuery(CommandType.Text,
"alter session set current_schema=:username",
DbType.String, 0,
CurrentUser);
}
public string CurrentUser { get { //get current asp.net user } }
}
AdoTemplate will use the connection/transaction object just like in your DAO layer.
Let me know how it goes..
Cheers,
Mark