I want to keep an entity, being configured by the user on several pages, in Session. This entity is loaded with NHibernate, with some of its properties/collections lazy-loaded. Say:
Session["order"] = new Order(productRepository.Get(id))
on some next page, get Session["order"] and now work with it
but, at this time order is OK but its Product (and nested stuff) is broken since they're lazy-loaded in different session.
Is it possible to tell NHibernate that I want to eager-load my transient order's properties to the deepest level? Or, the only solution will be to eager-load at the time of
productRepository.Get(id)
? Like,
Session.LoadNestedProperties(order, Eager);
Update: http://www.ribbing.net/index.php?option=com_content&task=view&id=35&Itemid=1 seems to solve the issue. However I'm not sure that reflection is great...
You could eager load all the graph with the objects you need, which is a little bit tricky.
Or you could try the following:
I assume your Order has a single Product. This Product is your problem since it becomes a detached object when the user visits the second page. You could use something like:
session.Update(myorder.Product)
to reattach the Product instance to the current session. After that lazy loading should work fine.
Related
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.
After a few years using NHibernate in Winforms and WPF, I still seem to have missed one very important point, which became too obvious when I ran this code snippet:
ISessionFactory sf = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c => c.Is(connectionString)))
.Mappings(x => x.FluentMappings
.AddFromAssemblyOf<MyClass>())
.BuildSessionFactory();
for (int i = 0; i < 100; i++)
{
new Task(()=>
{
Console.WriteLine("{0}, {1}",
i,
sf.OpenSession().QueryOver<MyClass>().List().Count);
}).Start();
}
This causes a lot of load, I surmise.
Honestly, the only thing I remember having read about Session handling is: Implement Unit Of Work, which proclaims atomar sessions. So, taking a look at the pattern, I have a few concerns/questions.
How does lazy loading fit in the picture? If I load my Data using one session, and then close it, lazy loading won't work. So, basically, the unit of work can not close / dispose the Session, meaning it is infinitely large.
Sessions have features like IsDirty. If loading and saving objects is done by separate sessions, how can this still be utilized?
EDIT: Oren Eini has stated the very same thing as being a problem in an early article of his. There, he says MicroManaging (=> use and immediate Dispose) cuts off NH functionality like LazyLoading and ChangeTracking. It seems to me though, that UnitOfWork is a Session MicroManagement pattern. So, what's the cleanest solution? Tracking changes myself and using MicroManagement? Monolithic sessions (= Memleak by design)? What if, unlike the example by Oren, you don't have many subdialogs that can restrict session lifetime?
How does lazy loading fit in the picture?
Lazy loading fits in the picture of one session. Once an object has been loaded, lazy loading allows traversing the object's graph without needing to know if an object property has already been loaded from the db, and without eagerly loading all the object graph.
Seems perfect, but there are issues though, like "n+1 select"
If I load my Data using one session, and then close it, lazy loading won't work.
Another session, loading the same object from db, will not benefit from the properties lazy loaded in the previous session.
So, basically, the unit of work can not close / dispose the Session,
meaning it is infinitely large.
I am not sure I understand this. I guess Session is the Unit of Work.
Sessions have features like IsDirty.
If loading and saving objects is done by separate sessions, how can this still be utilized?
Loading and saving should not be done in separate sessions. I guess it is the point of the IsDirty property.
This might give you many hints on NH handling : https://softwareengineering.stackexchange.com/q/100534
Hope this will help
Edit : about your second question. A usual web scenario would be like :
open a NH session
load a NH entity
transfer the NH entity properties in a POCO for display in the UI (keep track of Id, of course)
close the NH session
later on (user has made some changes and hits "Save" Button), open the NH session
load the corresponding NH entity (by its Id)
update the NH entity according to the new POCO fields
persist changes in the DB
close the NH Session
1,2 and 4 are parts of a first unit of work. 5,6,7,8 and 9 are parts of a second unit of work.
I am creating a new web app and would like some help on design plans.
I have "store" objects, and each one has a number of "message" objects. I want to show a store page that shows this store's messages. Using Doctrine, I have mapped OneToMany using http://symfony.com/doc/current/book/doctrine.html
However, I want to show messages in reverse chronological order. So I added a:
* #ORM\OrderBy({"whenCreated" = "DESC"})
Still I am calling the "store" object, then calling
$store->getMessages();
Now I want to show messages that have been "verified". At this point, I am unsure how to do this using #ORM so I was thinking I need a custom Repository layer.
My question is twofold:
First, can I do this using the Entity #ORM framework?
And second, which is the correct way to wrap this database query?
I know I eventually want the SQL SELECT * FROM message WHERE verified=1 AND store_id=? ORDER BY myTime DESC but how to make this the "Symfony2 way"?
For part 1 of your question... technically I think you could do this, but I don't think you'd be able to do it in an efficient way, or a way that doesn't go against good practices (i.e. injecting the entity manager into your entity).
Your question is an interesting one, because at first glance, I would also think of using $store->getMessages(). But because of your custom criteria, I think you're better off using a custom repository class for Messages. You might then have methods like
$messageRepo->getForStoreOrderedBy($storeId, $orderBy)
and
$messageRepo->getForStoreWhereVerified($storeId).
Now, you could do this from the Store entity with methods like $store->getMessagesWhereVerified() but I think that you would be polluting the store entity, especially if you need more and more of these custom methods. I think by keeping them in a Message repository, you're separating your concerns in a cleaner fashion. Also, with the Message repository, you might save yourself a query by not needing to first fetch your Store object, since you would only need to query to Message table and use its store_id in your WHERE clause.
Hope this helps.
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
The code:
public ChatMessage[] GetAllMessages(int chatRoomId)
{
using (ChatModelContainer context = new ChatModelContainer(CS))
{
//var temp = context.ChatMessages.ToArray();
ChatRoom cr = context.ChatRooms.FirstOrDefault(c => c.Id == chatRoomId);
if (cr == null) return null;
return cr.ChatMessages.ToArray();
}
}
The problem:
The method (part of WCF-service) returns an empty array. If I uncomment the commented line it starts working as expected. I have tried turning of lazy loading but it didnt help.
Also, when it works, I get ChatMessages with a reference to ChatRoom populated but not the ChatParticipant. They are both referenced by the ChatMessage-entity in the schema with both Id and Navigation Properties. The Ids are set and points to the right entities but on the client-side only the ChatRoom-reference has been populated.
Related questions:
Is an array the preferred method to return collections of EF-entities like this?
When making a change in my model (edmx) Im required to run the "Generate Database from Model..."-option before I can run context.CreateDatabase(). Why? I get some error message pointing to old SSDL but I cant find where the SSDL is stored. Is this created when I run this "Generate Database..."-option?
Is it safe to return entire entity-graphs to the client? Ive read some about "circular reference exeptions" but is this fixed in EF4?
How and when is references populated in EF4? If I have lazy-loading turned on I suspect only entities I touch is populated? But with lazy loading turned off, should the entire graph be populated always then?
Are there any drawbacks of using self-updating entities over ordinary entities in EF4? I dont need self-updating right now but I might do later. Can I upgrade easily or should I start with self-updating from the start?
Why cant I use entity-keys with type string?
Each of your questions needs a separate answer, but I'll try to answer them as briefly as possible.
First of all, in the code sample you provided, you get a ChatRoom object and then try to access a related object that is not included in your query (ChatMessages). If lazy loading is turned off as you had suggested, then you will need the Include("ChatMessages") call in your query, so your LINQ query should look like this:
ChatRoom cr = context.ChatRooms.Include("ChatMessages").FirstOrDefault(c => c.Id == chatRoomId);
Please ensure that your connection string is in your config file as well.
For the related questions:
You can return collections in any way you choose - I have typically done them in a List object (and I think that's the common way), but you could use arrays if you want. To return as a list, use the .ToList() method call on your query.
I don't understand what you're trying to do here, are you using code to create your database from your EDMX file or something? I've typically used a database-first approach, so I create my tables etc then update my EDMX from the database. Even if you generate your DB from your model, you shouldn't have to run CreateDatabase in code, you should be able to run the generated script against your DB. If you are using code-only then you need to dump the EDMX file.
You can generally return entity graphs to the client, should handle ok.
EF4 should only populate what you need. If you use lazy loading, it will automatically load things that you do not include in your LINQ query when you reference them and execute the query (e.g. do a ToList() operation). This won't work so well if your client is across a physical boundary (eg a service boundary) obviously :) If you don't use lazy loading, it will load what you tell it to in your query and that is all.
Self tracking entities are used for n-tier apps, where objects have to be passed across physical boundaries (eg services). They come with an overhead of generated code for each object to keep track of its changes, they also generate POCO objects which are not dependent on EF4 (but obviously contain generated code that would make the tracked changes work with the EF4 tracker). I'd say it depends on your usage, if you're building a small app that's quite self contained, and don't really care about separation for testability without the infrastructure in place, then you don't need to use self tracking entities. I say only use framework features when you need them, so if you're not writing an enterprise scale application (enterprise doesn't have to be big, but something scalable, highly testable, high quality etc) then no need to go for self tracking POCOs.
I haven't tried but you should be able to do that - that would be a candidate for a separate question if you can't get it to work :)