Inline
-----Original Message-----
From: kork [mailto:[email protected]]
Sent: den 25 november 2009 14:36
To: Castle Project Users
Subject: a question about atm and nhibernate facilities
hi all, i have a question about the castle ATM.
i'm using nhibernate facilities and i want to use transaction-per-
request pattern.
if i have this classes
[Transactional]
class DaoA
{
[Transaction]
void MethodA() { }
}
[Transactional]
class DaoB
{
[Transaction]
void MethodB() { }
}
this code will use 1 or 2 transaction?
class Container
{
void Run()
{
new DaoA().MethodA();
new DaoB().MethodB();
}
}
>> it will use 0 transactions as you don't have resolved for an instance of
Container through Windsor.
>> if you do resolve it, then, ASSUMING there aren't any lingering
asynchronous processing after method a, a called into another method that
uses a transaction, the transaction didn't get promoted to DTC, the
transaction isn't a file transaction, DaoA-instance isn't disposed from GC
since you aren't keeping a reference to it, you can connect successfully to
the database and you are using NHibernateFacility and have registered the
HttpModule to open an ISession for every request and have inherited
IWindsorAccessor from your HttpApplication so that NHibernate joins with the
transaction, THEN they would execute as two independent transactions as far
as I have fathomed.
>> change any of the assumptions and you may get other behavior.
>> Here's the relevant code:
if (CurrentTransaction != null)
{
if (transactionMode == TransactionMode.Requires || transactionMode
== TransactionMode.Supported)
{
transaction = ((StandardTransaction)
CurrentTransaction).CreateChildTransaction();
RaiseChildTransactionCreated(transaction, transactionMode,
isolationMode, distributedTransaction);
logger.DebugFormat("Child Transaction {0} created",
transaction.GetHashCode());
}
}
if (transaction == null)
{
transaction = InstantiateTransaction(transactionMode, isolationMode,
distributedTransaction);
if (distributedTransaction)
{
#if MONO
throw new TransactionException("Distributed transactions are
not supported on Mono");
#else
transaction.Enlist(new
TransactionScopeResourceAdapter(transactionMode, isolationMode));
#endif
}
RaiseTransactionCreated(transaction, transactionMode, isolationMode,
distributedTransaction);
logger.DebugFormat("Transaction {0} created",
transaction.GetHashCode());
}
>> so as you can see, if you have the default mode on the transaction (your
code does), it's TransactionMode.Requires and then it will join, but it will
join such that it will be committed as a sort of "resource" of the other
transaction. Since it uses System.Transactions internally, should the
transaction cross databases, it's promoted automatically IF you have the DTC
service running.
and if the response is 2 there's same not tricks way to have an unique
nhibernate transaction for web request?
>> yes, just start one at the beginning:
public MyHttpApp() { BeginRequest += s; }
void s(object s, EventArgs e) {
Container.Resolve<ITransactionManager>().StartTransaction( ... ) }
>> of course this would be suboptimal since you have NHibernate's
integration. Most of the time you just allow NHibernate to manage your
transactions in your data-layer. You need one to persist changes nowadays.
>> if you REALLY need a transaction per request, in the database (why would
you?) as well, for even things like static content on your
WebDAV.exe/Cassini.exe or for any dynamic content what-so-ever, just do this
instead of method s above:
S(obj s, EventArgs e) { var k =
global::Castle.Facilities.NHibernateIntegration.Components.Web.SessionWebMod
ule.SessionKey;
var ctx = ((HttpApplication)s).Context;
ITransaction tx;
ctx.Items["my_awesome_tx"] = tx =
ctx.Items[k].OpenSession().BeginTransaction();
}
And
s_end_request(obj s, EA e) { ctx ... .Items["my_awesome_tx"] as
ITransaction).Commit() unless ctx.Server.GetLastError() != null; etc }
>> beware that Request.End() skips half the steps on IIS/ASP.Net that would
otherwise fire for a given request-unit-of-work so you might want to take
this into calculation if you choose to go down this path.
i'm using normal asp.net pages and the access to the db happens in
different nested controls so i haven't a single class as the container
of my example where i can simply add the Transaction/Transaction
attribute to group the nested transactions in a unique.
>> you can just resolve IMyServiceClass-instance which uses tx-interception,
and then pass it to these controls.
>> beware of async pages as well as then HttpContext.Current.Items (this
collection is thread-static + thread migrated) might be different as you're
executing in the thread pool.
>> Cheers,
>> Henrik
--
You received this message because you are subscribed to the Google Groups
"Castle Project Users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/castle-project-users?hl=en.
--
You received this message because you are subscribed to the Google Groups
"Castle Project Users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/castle-project-users?hl=en.