Transactions are mandatory for all DB accesses including reads, not just
writes.
code should be
private static void GetUser(ISessionFactory sessionFactory, int
userId)
{
ISession session = sessionFactory.GetCurrentSession();
using (var tx = session.BeginTransaction())
{
User user = session.Get<User>(userId);
tx.Commit();
}
}
John Davidson
On Thu, Feb 10, 2011 at 6:44 AM, Paul Allington <
[email protected]> wrote:
> I've also written a really simple web example to show a data entity hanging
> around in memory after the request is finished with:
>
> If I call "Get<User>(userId)" - the User object is still in memory once the
> request has ended (GC has been run)......aaany ideas?
>
> *Code sample:*
>
> protected void Page_Load(object sender, EventArgs e)
> {
> int userId = CreateUser(SessionSource.Instance.SessionFactory);
> GetUser(SessionSource.Instance.SessionFactory, userId);
> }
>
> private static void GetUser(ISessionFactory sessionFactory, int
> userId)
> {
> ISession session = sessionFactory.GetCurrentSession();
> User user = session.Get<User>(userId);
> }
>
> private static int CreateUser(ISessionFactory sessionFactory)
> {
> User user = new User();
> user.Created = DateTime.Now;
> user.Email = "[email protected]";
> user.Enabled = true;
> user.FirstName = "first name";
> user.LastName = "last name";
> user.Password = "password";
> user.ScreenName = "firstname lastname";
> ISession session = sessionFactory.GetCurrentSession();
> session.SaveOrUpdate(user);
> return user.Id;
> }
>
> *HttpModule*:
>
>
> private static void BeginRequest(object sender, EventArgs e)
> {
> ISession session =
> SessionSource.Instance.SessionFactory.OpenSession();
> ManagedWebSessionContext.Bind(HttpContext.Current, session);
> }
>
> private static void EndRequest(object sender, EventArgs e)
> {
> ISession session =
> ManagedWebSessionContext.Unbind(HttpContext.Current,
> SessionSource.Instance.SessionFactory);
>
> if (session == null) return;
>
> session.Close();
> session.Dispose();
> }
>
> *Session factory:*
>
> SessionFactory = Fluently.Configure()
>
>
> .Database(MsSqlConfiguration.MsSql2008.ConnectionString(DataConfig.ConnectionString))
> .Mappings(x => GetFluantMappings(x)
> .Conventions.Add(typeof
> (EnumConvention)))
> .ExposeConfiguration(c =>
> {
>
> c.SetProperty("generate_statistics", "true");
>
> c.SetProperty("current_session_context_class", "managed_web");
>
> c.SetProperty("cache.use_second_level_cache", "false");
>
> c.SetProperty("cache.use_query_cache", "false");
>
> })
> .BuildSessionFactory();
>
> *
> *
> *Paul Allington [image: See my
> profile]<http://www.intelligentpenguin.co.uk/about/theteam/paul>
> *
> *T:* 01799 522 665
> *M:* 07973 145 754
> *E:* [email protected]
> *W:* www.intelligentpenguin.co.uk
> *W:* www.creative-penguin.co.uk
> [image: Intelligent Penguin] <http://www.intelligentpenguin.co.uk> For
> highly creative & technically brilliant websites, and on-line management
> systems
>
> ------------------------------------------------------------------------------
> My
> profiles: [image: Facebook] <http://www.facebook.com/paulallington>[image:
> LinkedIn] <http://uk.linkedin.com/in/paulallington>[image:
> Twitter]<http://twitter.com/paulallington>
> Contact me: [image: Google Talk/]phallington [image: Skype/]paul-allington
> [image: Y! messenger/]paul_allington
>
>
>
>
> On Thu, Feb 10, 2011 at 10:50 AM, Paul Allington <
> [email protected]> wrote:
>
>> I've just written a reeeally simple console app to try and find where this
>> unmanaged memory is coming from...8.7MB to 22MB is quite a jump - what's
>> using it? Is that really runtime?
>>
>> Results:
>>
>> *Start of the App*
>> Task Manager: 5,976 K
>> Gen 1 Objects: 39.77 KB
>> Gen 2 Objects: 0
>> Large Object Heap: 35.58 KB
>> Unused allocated memory: 28.25 KB
>> Unmanaged 8.766 MB
>>
>> *After factory is created*
>> Task Manager: 29,852 K
>> Gen 1 Objects: 512.2 KB
>> Gen 2 Objects: 799.3 KB
>> Large Object Heap: 47.61 KB
>> Unused allocated memory: 8.91 MB
>> Unmanaged 21.95 MB
>>
>> *Paul Allington [image: See my
>> profile]<http://www.intelligentpenguin.co.uk/about/theteam/paul>
>> *
>> *T:* 01799 522 665
>> *M:* 07973 145 754
>> *E:* [email protected]
>> *W:* www.intelligentpenguin.co.uk
>> *W:* www.creative-penguin.co.uk
>> [image: Intelligent Penguin] <http://www.intelligentpenguin.co.uk> For
>> highly creative & technically brilliant websites, and on-line management
>> systems
>>
>> ------------------------------------------------------------------------------
>> My
>> profiles: [image: Facebook] <http://www.facebook.com/paulallington>[image:
>> LinkedIn] <http://uk.linkedin.com/in/paulallington>[image:
>> Twitter]<http://twitter.com/paulallington>
>> Contact me: [image: Google Talk/]phallington [image: Skype/]paul-allington
>> [image: Y! messenger/]paul_allington
>>
>>
>>
>>
>> On Thu, Feb 10, 2011 at 9:21 AM, Paul Allington <
>> [email protected]> wrote:
>>
>>> Thanks for that - very helpful.
>>>
>>> The snapshot is being taken after the request has completed. Am I the
>>> only one who has a large chunk of unmanaged memory allocated when I use
>>> nhibernate?
>>>
>>> *
>>> *
>>> *Paul Allington [image: See my
>>> profile]<http://www.intelligentpenguin.co.uk/about/theteam/paul>
>>> *
>>> *T:* 01799 522 665
>>> *M:* 07973 145 754
>>> *E:* [email protected]
>>> *W:* www.intelligentpenguin.co.uk
>>> *W:* www.creative-penguin.co.uk
>>> [image: Intelligent Penguin] <http://www.intelligentpenguin.co.uk> For
>>> highly creative & technically brilliant websites, and on-line management
>>> systems
>>>
>>> ------------------------------------------------------------------------------
>>> My
>>> profiles: [image: Facebook] <http://www.facebook.com/paulallington>[image:
>>> LinkedIn] <http://uk.linkedin.com/in/paulallington>[image:
>>> Twitter]<http://twitter.com/paulallington>
>>> Contact me: [image: Google Talk/]phallington [image: Skype/]paul-allington
>>> [image: Y! messenger/]paul_allington
>>>
>>>
>>>
>>>
>>> On Wed, Feb 9, 2011 at 10:20 PM, John Davidson <[email protected]>wrote:
>>>
>>>> The code from Jason will work, but it assumes that the entire session
>>>> happens in one transaction, which probably works in 99% of use cases, while
>>>> the other 1% needs a different management strategy. This can be done by
>>>> ensuring that a commit happens at the end of your first logical work unit
>>>> and that it starts a new transaction for the second work unit.
>>>>
>>>> The other piece to check is that the http module is actually being used.
>>>> It is bound into the aspx pipeline by the web.config file. The Register
>>>> RequestHTTPModule section is important.
>>>>
>>>> Finally there is the question of when and how the memory snapshot is
>>>> being generated. The snapshot needs to be taken when there is no active
>>>> requests, i.e. when a web page has just completed loading, rather than
>>>> while
>>>> it is loading.
>>>>
>>>>
>>>> On Wed, Feb 9, 2011 at 4:33 PM, Paul Allington <
>>>> [email protected]> wrote:
>>>>
>>>>> Thanks - that's useful, I'll clean up the request code. Perhaps it's
>>>>> just the way it managed the objects, but it doesn't explain the 30MB of
>>>>> unmanaged memory - this I can't profile. Any clue what this could be?
>>>>>
>>>>> *
>>>>> *
>>>>> *Paul Allington [image: See my
>>>>> profile]<http://www.intelligentpenguin.co.uk/about/theteam/paul>
>>>>> *
>>>>> *T:* 01799 522 665
>>>>> *M:* 07973 145 754
>>>>> *E:* [email protected]
>>>>> *W:* www.intelligentpenguin.co.uk
>>>>> *W:* www.creative-penguin.co.uk
>>>>> [image: Intelligent Penguin] <http://www.intelligentpenguin.co.uk> For
>>>>> highly creative & technically brilliant websites, and on-line management
>>>>> systems
>>>>>
>>>>> ------------------------------------------------------------------------------
>>>>> My
>>>>> profiles: [image: Facebook] <http://www.facebook.com/paulallington>[image:
>>>>> LinkedIn] <http://uk.linkedin.com/in/paulallington>[image:
>>>>> Twitter]<http://twitter.com/paulallington>
>>>>> Contact me: [image: Google Talk/]phallington [image: Skype/]paul-allington
>>>>> [image: Y! messenger/]paul_allington
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Wed, Feb 9, 2011 at 9:05 PM, Jason Meckley
>>>>> <[email protected]>wrote:
>>>>>
>>>>>> I think the problem is your transaction management in end request.
>>>>>> rollback if error (good) else flush session (bad). call
>>>>>> transaction.commit()
>>>>>> instead and dispose of the transaction.
>>>>>>
>>>>>> some things to consider:
>>>>>> 1. sessions are cheap so just create one for each request and dispose
>>>>>> when the request ends.
>>>>>> 2. all NH actions should be wrapped in a transaction if every request
>>>>>> will require db access begin/end the transaction with the session. if not
>>>>>> all WCF calls require NH, than manage the transaction with a decorator
>>>>>> around the WCF call (similar to Filters in MVC frameworks)
>>>>>>
>>>>>> I would start by cleaning up the module code
>>>>>>
>>>>>> //begin request
>>>>>> var session = SessionFactory.OpenSession();
>>>>>> session.BeginTransaction();
>>>>>> ManagedWebSessionContext.Bind(HttpContext.Current, session);
>>>>>>
>>>>>> //end request
>>>>>> var session = ManagedWebSessionContext.Unbind(HttpContext.Current,
>>>>>> SessionFactory);
>>>>>> using(session)
>>>>>> {
>>>>>> using(var tx = session.Transaction)
>>>>>> {
>>>>>> if(Server.LastException == null)
>>>>>> {
>>>>>> tx.Commit();
>>>>>> }
>>>>>> else
>>>>>> {
>>>>>> tx.Rollback();
>>>>>> }
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> that's it. now if you want to manage the transaction per WCF action
>>>>>> then the module would only manage the session
>>>>>> //begin request
>>>>>>
>>>>>> ManagedWebSessionContext.Bind(HttpContext.Current,
>>>>>> SessionFactory.OpenSession());
>>>>>>
>>>>>> //end request
>>>>>> ManagedWebSessionContext.Unbind(HttpContext.Current,
>>>>>> SessionFactory).Dispose();
>>>>>>
>>>>>> and a WCF decorator would manage the transaction. something like
>>>>>> //decorator... wcfservice is the original/base implementation
>>>>>> using(var txt = SessionFactory.GetCurrentSession().BeginTransaction())
>>>>>> {
>>>>>> try
>>>>>> {
>>>>>> wcfservice.Proceed();
>>>>>> tx.Commit();
>>>>>> }
>>>>>> catch
>>>>>> {
>>>>>> tx.Rollback();
>>>>>> throw;
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> --
>>>>>> You received this message because you are subscribed to the Google
>>>>>> Groups "nhusers" 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/nhusers?hl=en.
>>>>>>
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "nhusers" 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/nhusers?hl=en.
>>>>>
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "nhusers" 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/nhusers?hl=en.
>>>>
>>>
>>>
>>
> --
> You received this message because you are subscribed to the Google Groups
> "nhusers" 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/nhusers?hl=en.
>
--
You received this message because you are subscribed to the Google Groups
"nhusers" 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/nhusers?hl=en.