Im new in Nhibernate.
I have application with lazy loading.
I want to write method
public User GetUser(int id)
in my UserPersister class.
Later, in application I want use some referenced property like User.Role or User.Address.
It wan`t work if I close Session that I used to retreive user.
My first idea was to create Singleton Session and I will be able to get all data then.
I read some articles that it is bad idea becouse of performance and memory leaking.
Is it true? What is the solution of this problem ?
Regards
Martin
Have a look at Effectus for a simple approach to WPF + NHibernate.
First of all remember that NH session != sqlconnection. Having global (singleton) session is generally not good idea even in wpf because you can reach multithread scenario sooner or later. But i definitelly wouldn't argue against with performance nonsense in your case.
I would suggest you to open it for shortest possible time to complete the usecase. Perform kind of analysis where you identify usecases of your app as "sessions" with limited lifespan. For example shopping cart. You start and you finish. You can make session live until you finish such usecase. Then throw it away...
Related
Igor,
I was wondering if you might have some hints as to how I might go about implementing record level, or possibly, field level security using ActiveJDBC. I played around with extending the Model class to override some of the methods from Model. However, it's not a very "elegant" solution and started to become rather messy. I know that your Model class has hooks for certain events, but nothing that seems to stick out to me for modifying behavior. I was able to catch the "set" and "get" calls without too much hacking to implement simple "field level security" type logic, but it became very difficult to overload other methods such as those methods that return a List.
Again, I'm looking more for suggestions on how to do this without actually having to change the Model or LazyList class (though I could go that route as well).
I've been using ActiveJDBC for a number of years now, and it's really been a great framework to build on. Thanks for all your hard work!
Haha, thanks for addressing me directly by name!
We do this all the time, as saving passwords in the database in clear text is not that smart. Usually, we use callbacks for specific models: http://javalite.io/lifecycle_callbacks
What you want to do, is register a callback: http://javalite.io/lifecycle_callbacks#registration-of-external-listeners
or override a method beforeSave on a model, since each model is also an event listener for its events.
I'm working on an iPhone/iOS game, and I was wondering if I could/should use a global object for statistic tracking between scenes. Now wait, before you jump down my throat - yes, it goes against everything I know about good code, but I don't think that concurrency is going to be an issue in this case. The structure of my game is similar to an Oregon Trail kind of affair with a sprinkling of Civilization thrown in for good measure - since it's not real-time I can ensure that only one process will be accessing the object in question at one time, and thus I'm pretty sure concurrency will not be an issue at all. Basically every scene will need access to most of the data (population, current technology level, current date, current map state) and so I'm wondering if I can get away with using a global object to store this data.
Everything I ever learned in college screams that this is a Bad Idea, but the sneaky programmer part of me keeps whispering "it won't be that bad, just this once couldn't hurt." And without worrying about concurrency, I'm kind of leaning towards the sneaky programmer. Is there any other reason I should avoid using a global object for this kind of statistic tracking?
Can you explain what you mean by global object?
If you're talking about the singleton design pattern, there's nothing wrong using it.
If you're talking about an object instance that different threads can modify, there's nothing wrong doing this, if you're careful and use #synchronize on objects correctly
But I think it iS wrong to assume your application is going to be mono thread during its whole lifecycle for the reason that iOS can do stuff behind the scene and that it would prevent you to do any asynchronous processing (and I also assume any game requires some non-trivial processing and this processing should be done on a background thread to let the main thread be as responsive as possible on user interactions)
I have been using Spring.NET and NHibernate for some years and I am very satisfied. However, I was always playing around with multi threading, Reactive Extensions and eventually Task Parallel Library which is a great framework. Unfortunately all kind of multithreading approaches fail because of NHiberntate's session which is not thread safe.
I am asking you how can I benefit from parallel programming and still utilising NHibernate.
For instance: I have a CustomerRegistrationService class which method Register performs several tasks:
ICustumer customer = this.CreateCustomerAndAdresses(params);
this.CreateMembership(customer);
this.CreateGeoLookups(customer.Address);
this.SendWelcomeMail(customer);
The last two methods would be ideal candidates to run parallel, CreateGeoLookups calls some web services to determine geo locations of the customer's address and creates some new entities as well as updates the customer itself. SendWelcomMail does what it says.
Because CreateGeoLookups does use NHibernate (although through repository objects so NHibernate is acutally hidden via Interfaces/Dependency Inection) it won't work with Task.Factory.StarNew(...) or other Threading mechanisms.
My question is not to solve this very issue I have described but I would like to hear from you about NHibenrate, Spring.NET and parallel approaches.
Thank you very much
Max
In NH its the ISession that isn't thread-safe but the ISessionFactory is entirely thread-safe, easily supporting what it seems you are after. If you have designed your session-lifecycle-management (and the repositories that depend upon it) such that you assume one single consistent ISession across calls, then, yes, you will have this kind of trouble. But if you have designed your session-handling pattern to only assume a single ISessionFactory but not to make assumptions about ISession, then there is nothing inherently preventing you from interacting with NH in parallel.
Although you don't specifically mention your use case as being for the web, its important to take note that in web-centric use-cases (e.g., what is a pretty common case for Spring.NET users as well as many other NH-managing-frameworks), the often-used 'Session-Per-Request' pattern of ISession management (often referred to in Spring.NET as 'Open Session In View' or just 'OSIV') will NOT work and you will need to switch to a different duration of your ISession lifecycle. This is because (as the name suggests) the session-per-request/OSIV pattern makes the (now incorrect in your case) assumption that there is only a single ISession instance for the duration of each HttpRequest (and presumably you would want to be spawning these parallel NH calls all within the context of a single HttpRequest in the web use case).
Obviously in the non-web case where there's rarely a similar concept to session-per-request you wouldn't be as likely to run into this issue as session-lifecycle management is rarely as fine-grained/short-lived as it in web-based applications.
Hope this helps.
-Steve B.
This a difficult thing you ask for. The DTC has to be taken with care.
The only solution i may know is the use of reliable, transactional messaging (e.g. MSMQ + NServiceBus/MassTransit).
Such a design enables you to do this. It would look like this:
var customerUid=CreateCustomers();
Bus.Publish(new CustomerCreatedEvent() { CustomerUid = customerUid});
Then you could use two event handlers (Reactors) that handle the event and send an EMail or create the lookups.
This won´t allow you sharing the Transaction either but will ensure that the Reactors are run (in a new Transaction) when the creation of the customer suceeded.
Also this has nothing to do with the TPL.
Well thank you for answering. I know that the 'ISession that isn't thread-safe but the ISessionFactory is entirely thread-safe'. My problem in the above code for example is that the whole operation is wrapped in one transaction. So this.CreateCustomerAndAdresses(params) on main thread #1 will use for instance ISession #1 with transaction #1. Calling the other three in parallel will create three more threads and three more sessions and transactions which leads to database timeouts in my case. My assumption is that the transaction #1 is not successfully commited because it waits for the three concurrent tasks to complete. But the three concurrent tasks try to read from the database while a transaction is still active leading to deadlocks/timeouts.
So is there some way to tell the other threads/sessions not to create a new transaction but use the main transaction #1?
I am using the TxScopeTransactionManager from Spring.NET which utilises DTC (System.Transactions). I have googled that maybe System.Transactions.DependentTransaction could work but do not have a clue how to integrate it in my Spring.NET transaction managed scenario.
Thanks
If I have 10 database calls on my web page, and none of them require any transactions etc.
They are simply getting data from the database (reads), should I still use the unit of work class?
Is it because creating a new session per database call is too expensive?
With NHibernate, session factory creation is very expensive (so you'll want to cache the session factory once it's created, probably on the HttpApplication) but session creation is very cheap. In other words, if it keeps your code cleaner, multiple session creations is not necessarily a bad thing. I think the NH documentation says it best:
An ISessionFactory is an
expensive-to-create, threadsafe object
intended to be shared by all
application threads. An ISession is an
inexpensive, non-threadsafe object
that should be used once, for a single
business process, and then discarded.
So, using the UoW pattern is probably not more efficient due to the extra overhead, but it's a good practice and the overhead is probably not going to hurt you. Premature optimization and all that.
Yes, you should use a transaction. From Ayende's blog:
"NHibernate assume that all access to the database is done under a transaction, and strongly discourage any use of the session without a transaction."
For more details, here's a link to his blog posting:
http://ayende.com/Blog/archive/2008/12/28/nh-prof-alerts-use-of-implicit-transactions-is-discouraged.aspx
We're using the DTO pattern to marshal our domain objects from the service layer into our repository, and then down to the database via NHibernate.
I've run into an issue whereby I pull a DTO out of the repository (e.g. CustomerDTO) and then convert it into the domain object (Customer) in my service layer. I then try and save a new object back (e.g. SalesOrder) which contains the same Customer object. This is in turn converted to a SalesOrderDTO (and CustomerDTO) for pushing into the repository.
NHibernate does not like this- it complains that the CustomerDTO is a duplicate record. I'm assuming that this is because it pulled out the first CustomerDTO in the same session and because the returning has been converted back and forth it cannot recognise this as the same object.
Am I stuck here or is there a way around this?
Thanks
James
You can re-attach an object to a session in NHibernate by using Lock - e.g.
_session.Lock(myDetachedObject, NHibernate.LockMode.None);
which may or may not help depending on exactly what is happening here. On a side note, using DTO's with NHibernate is not the most common practice, the fact that NHibernate (mostly) supports persistence ignorance means that typically DTO's aren't as widely used as with some other ORM frameworks.
It's really about how NHibernate session works. So if you within a session pull an instance of your CustomerDTO and then after a while you should get the same CustomerDTO (say by primary key) - you actually will get reference to the very same object like you did in your first retrieval.
So what you do is that you either merge the objects by calling session.Merge or you ask your session for the object by calling session.Get(primaryKey) do your updates and flush the session.
However as suggested by Steve - this is not usually what you do - you really want to get your domain object from the datastore and use DTOs (if neede) for transferring the data to UI, webservice whatever...
As others have noted, implementing Equals and GetHashCode is a step in the right direction. Also look into NHibernate's support for the "attach" OR/M idiom.
You also have the nosetter.camelcase option at your disposal: http://davybrion.com/blog/2009/03/entities-required-properties-and-properties-that-shouldnt-be-modified/
Furthermore, I'd like to encourage you not to be dissuaded by the lack of information out there online. It doesn't mean you're crazy, or doing things wrong. It just means you're working in an edge case. Unfortunately the biggest consumers of libraries like NHibernate are smallish in-house and/or web apps, where there exists the freedom to lean all your persistence needs against a single database. In reality, there are many exceptions to this rule.
For example, I'm currently working on a commercial desktop app where one of my domain objects has its data spread between a SQL CE database and image files on disk. Unfortunately NHibernate can only help me with the SQL CE persistence. I'm forced to use a sort of "Double Mapping" (see Martin Fowler's "Patterns of Enterprise Application Architecture") map my domain model through a repository layer that knows what data goes to NHibernate and what to disk.
It happens. It's a real need. Sometimes an apparent lack in a tool indicates you're taking a bad approach. But sometimes the truth is that you just truly are in an edge case, and need to build out some of these patterns for yourself to get it done.
I'm assuming that this is because it
pulled out the first CustomerDTO in
the same session and because the
returning has been converted back and
forth it cannot recognise this as the
same object.
You are right. Hibernate can't. Consider implementing Equals and Hashcode to fix this. I think a re-attach may only work if you haven't loaded the object within this session.