How do I tell if enteties changed in the current transaction with nhibernate? - nhibernate

I have a web service that uses nhibernate, calls to the web service go to a simple method that opens the session, begins a transaction and then calls code I don't control that sometimes modifies entities, after that code returns the transaction is commited.
I need to add some extra processing inside the transaction that only happens if entities actually changed, I don't control the code that is called from the web service and I can't change it or make it return any additional information.
That code may even flush the nhibernate session.
How can I tell if any entity changed in the current transaction?
Thanks

ISession has .IsDirty() that would indicate that upon flush, something would be written to the database.

Related

Entity Framework 4.1: how to work with per call life time data context?

According to this post, I am using a data context per call, so in each method of my WCF service, I use a using block to create a new data context.
But I have some doubts in the form to work in this way.
For example, I use a method getAllCLients() from my repository to get all the clients of the data base, then the service send to the client that call the method a list with all the clients. Then the user modify the information of some of them, three for example. The modify client perhaps I can add to a list that have the modified clients.
When I want to update this three clients, I can call a method updateClients() which receive a list of modified clients. How I am use a new data context per each method, in updateCients() get a new dataContext, without entities, so I think that I have to follow this steps:
1.- create a new data context which has the clients that I want to update. SO I need to specified the conditions for that. This is an extra operation (I get the clients before with the getAllClients() method), so I need to get again the clients.
2.- go throw the clients collection of the DBSet (I use EF 4.1) and change the information. This makes me to go throw the list that I receive from the client application too. So I must to go throw two lists. This needs resources.
3.- save the changes. This is needed anyway, so it has no required more work.
There is any way to make the step 2 easily? exist some method in dataContext to pass the values from my modified client to the client in the data context? I use POCO entities, perhaps it exists an easy way to do that.
Other question is about concurrency. If I control the concurrency with pesimistic concurrency that allow EF (with a timestamp field for example), is it better to call the updateClient() one for each client or better to pass a list with all the clients? I mean that if I use a list as parameter, if there is a concurrency issue with one client,the second for example, the first client will be update correctly, but the second not and the third neither. How can I notify to the user that there is problems with some clients?
To resume, I would like to know the best way to make updates when I have a short life datacontext.
Thanks.
Daimroc.
The service is disconnected scenario so when your client passes backs modified records you just need to process them as modified. You don't need to load all records from database for that.
public void SaveClients(List<Client> modifiedClients)
{
using (var context = new Context())
{
modifiedClients.ForEach(c =>
{
context.Entry(c).State = EntityState.Modified;
});
context.SaveChanges();
}
}
If you are using per call service and every service operation needs context you can move your context instancing to service constructor because service instance will live only to server single service call = you don't need using for every call. If you do that don't forget to implement IDisposable on your service to dispose context.
Other question is about concurrency. If I control the concurrency with
pesimistic concurrency that allow EF (with a timestamp field for
example), is it better to call the updateClient() one for each client
or better to pass a list with all the clients?
EF doesn't support pesimistic concurrency out of the box. Using timestamp is optimistic concurrency because it allows others to use the record. Pesimistic concurrency is application logic where other client is not able to select locked record for update.
The concurrency is resolved per record but the problem in this case is transaction. Each call to SaveChanges results in transaction used to process all changes in the database. So if any of your modified records is not up to date you will get concurrency exception and whole transaction is rolled back = no record is updated.
You can still overcome the issue by passing list of modified records to the service (reducing roundtrips between client and service is a best practice) but you can process each record separately by calling SaveChanges for every single record. Anyway this should be very carefully considered because each call to SaveChanges is like separate unit of work - is it really what you want?
Btw. the best practice is to make your service statless. You should avoid maintaining data between service calls and this example really doesn't need it.

How can I get Entity Framework and WCF to work with transactions? Okay...what's the secret?

I've been trying several different ways in order to get a simple set of transactions to work for a simple WCF client/server situation. My WCF server has a class level declaration of the Entity Framework class for my database access and several methods to modify data and a method to SaveChanges. I'm using the Oracle Data Access (ODP.NET).
For instance I want to call a modification from the client and then a separate call to save the changes in the WCF service. It doesn't work. Basically, everything executes fine, but when the second call to save the changes is made, the WCF service no longer has the original context and therefore no changes are saved (and, consequently, the previous call that made the changes was automatically rolled back).
I'm utilizing Transaction scope around both operations in my client and executing Complete() after done. My WCF services have OperationContract's that use [TransactionFlow(TransactionFlowOption.Mandatory)] and those method implementations use [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]. Finally, my web config is configured with a wsHttpBinding that has the transactionFlow property set to True.
I'm having no luck. No matter what I try, when I try hitting the service for the follow-up save, the EF context is already renewed.
This has nothing to do with transaction. Transaction works on transactional resource but without calling SaveChanges in the first request there was no transactional resource active because EF context is not part of the transaction - the database is and the database is affected only when you call SaveChanges. To make this work you don't need distributed transactions. You need session-full service and store the EF context in the service instance. It a client uses the same client proxy instance to communicate with the service for all requests the communication will be handled by the same service instance = same EF context instance which will remember changes from previous calls.
IMHO this is very bad architecture. Simply don't use it. Expose specialized methods on WCF service which will do changes and save them. If you need to execute these methods in transaction with other transactional resources use the real distributed transaction.
this might be a reason. Since your are making an update in the different context. context doesn't know that the object is update to have say the context that the object is modified and then you call savechnages(). See if it helps

WCF Custom Message Writing With Transaction Support

I'm using a custom message that inherits the System.Servicemodel.Channels.Message.
My custom message get IEnumerable collection which pulled from a database.
The WCF service is transactional (which is already tested).
MS-DTC is enabled.
Problem is, that when the protected override void OnWriteBodyContents(XmlDictionaryWriter writer) method is executed at the custom message, there is no transaction.
The System.Transactions.Transaction.Current is null. while executing the service the transaction flow is works fine, but when the message is written by WCF mechanism, it's seems like it's out of a transaction which cause the DB command (of pulling the data) to be executed without transaction.
Please note, that if I'm passing simple array instead of IEnumerable the DB action is executed under transaction, but I want it to be executed parallelly with the response writing.
Any ideas please, why the transaction is missing and what can be done to activate it?
many thanks!
Tamir.
Transaction are generally attached to your current thread or calling context. So if you are initiating transaction on different thread and message serialization is happing on another thread then transaction won't be available on that thread. You should look at TransactionScope and DependentTransaction for supporting such scenarios.

Castle Windsor Interceptor and Unit Of Work

Is Castle Windsor's Inteceptor mechanism considered to be a good/effective way of implementing the Unit of Work pattern?
My project involves Castle Windsor, the NHibernate Facility and of course NHibernate - all used in self-hosted WCF services.
Each service method normally requests from the Windsor container an instance of a helper class into which the WCF call is delegated. The helper class has an ISessionManager constructor argument which Windsor resolves via the NHibernate Facility.
The trouble is, the helper class is doing too much work. It has both logic and data access intermingled which means its difficult (virtually impossible) to test and difficult to read.
What I want is to re-arrange responsibilities
I don't want the WCF helper to know anything about transactions or sessions, so no ISessionManager constructor arg, no references to transactions and no ISession.
In order for the WCF helper to do data access, its going to have to rely on a new helper, dare I call it a DAO? or God forbid a repository, on which will be methods for fetching, querying, and possibly saving domain objects.
The problem with returning NHibernate proxied objects from a DAO is that if the session is closed before the entity is returned, any subsequent attempt to access collections on the domain object from the client code will result in an exception as the session is no longer there to be used to lazily fetch the required data. It's obvious really, but everyone new to NHibernate must hit this issue.
So if DAOs and Repos cant close the session, what does?
What I need is one NHibernate session per WCF service operation call, where several DAOs or Respositories can call OpenSession as much as they like, but they all get the same session, and ideally, any attempt to dispose the session would be ignored unless its the last Dispose. Not sure about the last bit, but maybe DAOs and repos just call ISessionManager.OpenSession and leave it to something else to flush and dispose the session.
I thought maybe I could use an interceptor which takes an ISessionManager, opens a session and starts a transaction, forwards the invocation, then if no exception occurs, commits the transaction and disposes the session, otherwise rolls back the transaction if any exception occurs.
Any thoughts?
So if DAOs and Repos cant close the
session, what does?session, what does?
Services own units of work, not DAOs. They demark units of work.
Spring manages transactions using AOP, so interceptors sound like a good bet for transaction management to me.
As far as sessions go, those are UI concepts, so it ought to be the web or desktop UI controller that opens the session, marshals services to fulfill use cases, and closes the session when it's complete.
Castle.Service.Transactions also ties well together with the rest of the castle stack and allow you to use AOP to handle transactions.
Have a look at v3!
https://github.com/haf/Castle.Services.Transaction
And the wiki there!
I also created a new NHibernate Facility:
https://github.com/haf/Castle.Facilities.NHibernate/wiki/NHibernate-Facility---Quick-Start

NHibernate Transactions in Open View per Session - suggested practices?

Cleaning up some transactional logic and wondered how other people were handling it.
Ayende's recommendation seems to be to handle transactions at the service boundary. This is a ASP.NET web app though, so it hasn't got a clear cut service boundary, at least not right now.
What do people do?
Create a single transaction per request in a HttpModule and handle commit on EndRequest, rollback on Error?
Create transactions in the actual "services" in the application and handle it multiple places?
Something else?
You can use a IoC Container for your service layer and the container can manage the transaction and the Nibenrate Session.
Your WebApp Controller => call (A) Service Layer => call (B) one or several DAO methods /operations.
The IoC container like Spring.NET will manage te TX scope, by example at (A) and will provide a Session to your DAO in (B). The commit (or rollback) will be handled at the end of the service layer call.
Most people use a session-per-request strategy as stated in your first bullet point. However, I don't believe that the transaction needs to be committed on EndRequest. In many web pages it would be easier to commit the transaction based on user action (e.g. clicking submit) and let EndRequest just handle disposing the ISession.
As far as I can tell, there's no need to create an HttpModule as the same functionality can be created in global.asax: http://forum.hibernate.org/viewtopic.php?t=993041.