1

I have ninject make a new session on httpRequest and close it at the end of the httpRequest.

Now I learned through the nhibernate profile that I should always wrap everything in a transaction even queries(read).

This has caused so many bugs now in my code because I would retrieve an object back from the database and then do modifications to that object(mostly converting the utc time to local time).

These modifications should never be committed to the database but since I am now wrapping all my read queries in a transaction what requires a commit when I go and grab something else out of the database it does a commit and it see's that my object changed and saves the changes that should never be saved to the database.

I would use evict but then I lose lazy loading and I usually convert the times before I actually do some other queries that activate lazy loading.

What should I do?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
chobo2
  • 83,322
  • 195
  • 530
  • 832

2 Answers2

2

NHibernate 3.1 has a SetReadOnly() method on IQuery and ICriteria that ensures objects returned by the query will not be persisted by the session.

Dmitry S.
  • 8,373
  • 2
  • 39
  • 49
  • @Dmitry - Do you have link. I usually convert my stuff to a List() – chobo2 Jun 05 '11 at 04:58
  • I am not sure there is any documentation for the latest version of NH. You would do something like "criteria.SetReadOnly(true).List()". Here is a link to the feature in Jira: http://216.121.112.228/browse/NH-908 – Dmitry S. Jun 05 '11 at 05:02
  • @Dmitry - That seems to be put on the property in my fluent mapping. This won't work because there are times I need to update that column. – chobo2 Jun 05 '11 at 05:02
  • @Dmitry - I am using the linq way so I only IQueryable not Iquery. – chobo2 Jun 05 '11 at 05:04
  • Could you not reattach the objects to a session should you need to update any? – Adam Dymitruk Jun 05 '11 at 05:04
  • This method applies to the whole object and is not property specific. It will only apply to objects returned by the query. You are talking about a different concept of a readonly property. – Dmitry S. Jun 05 '11 at 05:07
  • I am not sure if it is available in the Linq provider which I would not use in production except for very simple queries. – Dmitry S. Jun 05 '11 at 05:08
  • @adymitruk - I would then be constantly taking it out of the session and putting back in. Since I use lazy loading in certain places but between those I am doing other queries to the database. – chobo2 Jun 05 '11 at 05:16
  • @Dmitry - You can also seem to do it at the session level and pass it in as an object. – chobo2 Jun 06 '11 at 03:24
2

I suggest that you load the results of the query into a viewmodel and then on a property of your viewmodel convert your date into local time. Because the viewmodel is NOT attached to the nHibernate session then you will not update the entity when your end of httpRequest commits the transaction.

A viewmodel is in effect a DTO and can be described as a flattened model of your data

See this post for more info (especially the answer regarding automapper)

edit It seems that your pain point is when the actual display of the data is performed. When I run into these problems I always use a displayFor template. On my view I use something along then lines of:-

Please note this is a contrived example:-

<h1>Books</h1>
<ul>
@foreach (var book in Model)
{
  <li>@book.Name @Html.DisplayFor(x=> book.UnitPrice, "Price")</li>
}   
</ul>

And then create a display template /Views/Shared/DisplayTemplates/Price.cshtml

@model decimal
<span>&pound;@Model</span>

Note: This view could perform your calculation via a helper etc...

This gives you quite a few benefits BUT it does mean that every where I use a price I have to use a display template. However I feel it is easier to remember that I need to use a display template for all my prices, dates etc, rather than some named helper that may get missed. It is always about training/conditioning yourself.

Its all open to debate and at the end of the day you need to feel comfortable with the way you work. However display templates seems to work better for me.

I should also point out that I urge you to think of this as a display problem and not try to provide a kludge retrieving your data from the database.

Community
  • 1
  • 1
Rippo
  • 22,117
  • 14
  • 78
  • 117
  • Yes I already use view models and auto mapper. One reason why I decided to do it on the result is for the simple reason that in past versions many times the conversion was forgotten or used to many times giving wrong results. So I figured once you get the object convert it to local time and forget about having to convert it. 2nd thing is automapper can't be used in this case as I would need to pass in the users timezone settings and automapper does not have the ability to pass in the timezone settings. – chobo2 Jun 05 '11 at 06:42
  • Ok, Is this is asp.net mvc application? also version 3? – Rippo Jun 05 '11 at 06:48
  • Yes mvc 3.0. Your template way probably would work but I jsut don't like templates as they give in my opinion less flexibility since you can't pass in like html attributes and stuff like that through the displayTemplate html helper. – chobo2 Jun 06 '11 at 03:24
  • I am now not sure the total scope of your problem, there is always a way but I think this needs to go to another question. – Rippo Jun 06 '11 at 05:30