The master page in my web application does authentication and loads up the user entity using a Get.
After this whenever the user object is needed by the usercontrols or any other class I do a Load.
Normally nhibernate is supposed to load the object from cache or return the persistent loaded object whenever Load of called. But this is not the behavior shown by my web application. NHprof always shows the sql whenever Load is called. How do I verify the correct behavior of Load?
I use the S#arp architecture framework.
Actually, calling Load on an entity not marked as lazy causes immediate loading. That is because non-lazy entities are never proxied. In this case, it just acts the same way as Get.
If you use Get, then a hit to a database is made.
If you use Load, no hit to a database is made, but the object (User in your case) is created with 'lazy loading'. So when you check a property it knows that you want data so it hits the database with a query to get the data.
If you want to get an object from cache, you need to consider 2 options.
First level cache, is a cache that is in use in ONE session. So when you close a session or load the same object in a different session, you get additional hits.
Second level cache works accross all sessions. If one session gets the object, the other session gets it from cache.
So what you want is probably a second level cache.
Related
I am working on a .NET Core Web API which needs to interact using EF Core 5.0.2 with an Azure SQL database.
I have different repository methods where I am interacting with DbContext to add/edit/delete records for different DbSet.
For example:
UserRepository.AddUser(userdata);
Implementation of AddUser is like this,
ourDbContext.UserTable.AddAsync(userdata);
So in user service method, am calling different repository method sequentially and none of those methods call ourDbContext.SaveChangesAsync() individually. A single call to SaveChanges is present after all the repository methods calls which is acting like a unit of work pattern for all the calls as single transaction.
Example:
UserRepository.AddUser(userdata);
ActivityRepository.AddActivity("New User got added");
ourDbContext.SaveChangesAsync();
So my question is: if any saving changes to any of the tables/entities fails, will the previous successful tables change will be rolled back?
For example, suppose this operation
UserRepository.AddUser(userdata);
was successful and the new user record was added to the User table.
But this was not successful:
ActivityRepository.AddActivity("New User got added");
So no activity record was added to the Activity table.
Will SaveChangesAsync() be able to handle this situation automatically and will roll back User table new changes as well?
If not are we supposed to wrap the above codes with transaction scope? Or what is the recommended way to do it.
Briefly how DbContext's Change Tracker works:
You load entities: ChangeTracker remembers current values of all loaded entities (except you use AsNoTracking())
You have modified loaded entities, delete, add new.
You call SaveChanges: ChangeTracker starts searching which objects are changed since last load by comparing with previous values.
DML SQL is generated and everything saved in one SQL statement or in several statements in Transaction.
So, if you have one DbContext for each repository, you do not need to worry about rollbacking, just do not call SaveChanges(). For sure for restart process, you have to recreate DbContext because it contains not needed state.
I have problem with cache in Fluent NHibernate. I want to disable it for query by ID e.g.
session.Get<Person>(10);
Do you have any ideas ?
Are you referring to the first-level (session) cache?
You can refresh the state of an entity from the database by using Refresh, that is:
// Will get the state from the first-level cache if already present in the session:
var entity = Session.Get<EntityType>(entityId);
// Line below will update the entity with the current state from the database:
Session.Refresh(entity);
If you already hold the entity, call directly session.Refresh(person) on it instead of getting it again.
You may also evict it with session.Evict(person), causing it to no more be in the session, and no more tracked for changes either. Then discard it and eventually get it again later if you need.
Otherwise, this is unusual to consider it is a trouble getting it from the session cache. This is frequently a sign of bad session usage, such as using a same session across many user interactions (anti-pattern).
You can still do what Fredy proposes. Or call session.Clear() before getting for clearing the session cache (and losing all pending changes by the way).
Instead of a Person object that is mapped you could create a DTO for Person and do a QueryOver().
The PersonDTO object wont be cached in Nhibernates first-lvl-cache.
I am having a problem with the NHibernate default fetching behavior:
Lazy Fetching
Lazy fetching lets you decide how much of the object graph is loaded in the first database hit and which
associations should be loaded only when they’re first accessed. Lazy fetching is a foundational concept in
object persistence and the first step to attaining acceptable performance.
definition from: Nhibernate In Action, 2008
The problem:
I have a Submit button for example and I click it many times. On the server-side, I retrieve objects through navigating the object graph, for example:
User us = new GetUserById(userId);
if (us.Address.Street != null)
where One User has one Address on the DB Schema.
The first click works correctly, but if I click it quicker it thows the exception:
"Could not initialize proxy - no Session." Nhibernate
Is there any work around for this behavior?
thanks,
Tito Morais
you can use eager loading. see the below link:
http://nhibernate.info/doc/howto/various/lazy-loading-eager-loading.html
Using fluent NHibernate I have a property on a class mapped using Version
Version(x => x.Version);
When I save the object, the Version property gets incremented in the database as I would expect, but the value of the property on the object only seems to change sometimes.
using (var tx = session.BeginTransaction())
{
session.Merge(item);
tx.Commit();
item.Version; // Sometimes this is still 1, when I expect it to be 2.
}
The problem is then that if it remains as 1 and I make more changes and save again I get a StaleObjectStateException.
What's weird is that sometimes it works fine and the item.Version value does get correctly incremented, but I can't figure out the difference between the cases where it does and the cases where it doesn't.
I've tried searching but can't seem to find any documentation on this. Can anyone explain what NHibernates expected behaviour is with the Version mapping?
[NHibernate version 2.1.2]
From the ISession.Merge documentation:
Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session.
So, it will not modify item.
(I might add I have never used Merge in my apps. You might want to review how you are dealing with attached and detached entities)
Did you try
item = session.Merge(item);
tx.Commit();
?
You need to flush the session before the updated version will propagate up to your entities. Unless you flush the session, you are responsible for keeping the entities up to date yourself.
You should TYPICALLY let the session flush on its own when its closed. However, in some instances where you rely on database updates that happen via nhibernate and not settings you make to the entity itself, you might need to flush the session yourself after a commit. In this case be aware that when you flush the session ANY entities that are dirty will be committed. This may not be desirable so be sure that the scope is very limited.
We are using NHibernate to manage our persistence in a complex modular windows forms application - but one thought keeps bothering me. We currently open a session on launch and open all objects through that session. I am worried that all loaded objects get loaded into the NHibernate session cache, so that they cant be garbage collected, and ultimately we will end up with the whole database in memory.
This never happens with web applications because web page requests (and even better Ajax requests) represent the perfect short lived transaction so a session can be opened and closed to handle each request.
However if I load an tree of objects in my forms application and put then into a navigation pane on the screen they may stay their for the life of the application - and at any point the user may click on them, resulting in our code needing to navigate the object relationships to other objects (which only works within an NHibernate session).
What do StackOverflow readers do to keep the benefits of NHibernate without the issues I describe?
Ayende and company usually recommend using a session per "conversation". This usually makes the session lifetime last for very short operations, so it behaves more like a web app.
For your tree case, you can use Bruno's solution #2 just fine. The objects can be lazily mapped. Then, every time you need to access a child collection, you start a conversation and reconnect the parent via ISession.Lock. Then when the databinding is done, close that session. Not too much overhead to maintain, just a few lines of code in any form that needs to carry a conversation; you can extend Form and the controls you're using to do this automatically if you're feeling sassy.
The tricky part, then, is concurrent edits from different sessions. Let's not go there!
I open a session when I need one, and I'll close it when I know that I won't need it anymore.
More specifically, for instance, if I have a form which lets me edit Customer information for instance, I'll open a session when the form gets instantiated, and I'll close the Session when the form is closed.
When I have 2 instances of that form open, I also have 2 session open.
I can see a couple of alternatives:
Eager-load the object tree (which, from what I can gather from the documentation is the default)
Detach the objects, intercept the "click" event, and load the data from the database then, with a new session. This one forces you to take care of collections by yourself, instead of relying on nhibernate, which may fall outside of the scope of the question (which asks for the benefits of NHibernate, one of which is collection management)
You can take a look to my posts on how to use uNHAddins to work with session per conversation in a Windows Forms application (uNHAddins is a project with some additionsns to NHibernate led by Fabio Maulo, current NH Lead)
The first post is this
http://gustavoringel.blogspot.com/2009/02/unhaddins-persistence-conversation-part.html
From there you have links to uNHAddins trunk.