On my latest project, I thought it might be simpler to have only one context throughout the application. I notice that when I load a page that requires more then one query, it may return empty results.
For instance, I have a list of appointments and then a list of sales reps. They show up fine. Then I hit F5, sometimes all will keep being fine, but sometimes the appointment AND/OR rep list will be empty.
Is that a known issue with the single context apps? Is that design a bad one?
Is that a known issue with the single context apps? Is that design a bad one?
I believe yes, with simple web application, you might not see the difference, but with complex web application with many users and required high con-currencies, the problems would be:
DbContext implements Unit Of Work pattern under the hood, with internal cache inside, so keeping global DbContext for long time would cause the memory leak and pull tons of data from database and keep them in memory (internal cache) for the time being.
Think about Unit Of Work is a business transaction, and internal cache in Unit Of Work is just for this transaction, not for global, if the transaction is done, Unit Of Work should be disposed asap.
The best practice for DbContext in web application is keeping lifetime of DbContext as per request. If you use IoC container, most of IoC Container supports per request lifetime management.
Related
Recently I've been integrating NHibernate into our server application that exposes multiple services. The core service manages multiple instances of a class, and I understood that it is recommended to use the session-per-request pattern. So far so good.
One of the other services is a Site Settings service, which effectively manages a singleton: there is only a single instance of SiteSettings. I can follow the session-per-request pattern with this service as well, but it seems odd. Do I really need to create a new session for each request here? Why not create a single session for the service and keep using it? One of the advantages of the session-per-request pattern is that the session does not eventually cache all objects in the model. However, since I will only ever load a single instance in the session, I think this should not be a concern. Would I be better off using IStatelessSession rather than ISession?
Are there other reasons to use session-per-request here? One concern that comes to mind is what happens in case of a disconnection to the DB. Can I keep using the same session even after a DB error?
As an aside, I was thinking of storing each setting in its own column, which means I have to update the schema as settings are changed. I found this post: NHibernate Web Application - Managing User Preferences, where one of the comments is against using a table to store such configuration settings. I'm having a hard time coming up with alternatives (short of serializing the whole class and storing it as a blob). Are there different approaches?
Sessions aren't thread safe so I think you'd want more than one for your singleton
Can I keep using the same session even after a DB error?
No, presumably that would throw an exception and you're not supposed to reuse sessions after an exception. IMHO you should stick with the session per request pattern.
Are there different approaches?
Can you use a different row per config setting? So your User object would have a child collection of UserSetting objects. Each UserSetting would just be a key value pair.
I'm implementing a DAL using the Entity Framework. We have some DAL classes (I call them repositories) instantiating or receiving a context by parameter every time a method is called. I don't like that kind of behavior; I'm not documented about this issue but my common sense says me that context's instantiation consumes too much system resources. So:
Is context's instantiation expensive?
If you've answered "yes" to 1, how would you tackle this problem from a design viewpoint?
If you've answered "yes" to 1, how would you implement the solution in C#?
Which approach do you recommend to implement a DAL for a web application?
my common sense says me that context's instantiation consumes too much system resources
Common sense is nearly useless when it comes to optimization.
What exactly in the constructor of context do you suppose will be problematic? Have you read the source for it yet?
1) Is context's instantiation expensive?
Relative to what? Compared to the amount of time required to establish a database connection? Compared to the time it takes to perform your site's DNS lookup? Compared to the amount of time a browser might spend rendering your page?
The vast liklihood is that context's instantiation is not particularly time consuming compared to the time required to actually retrieve data across the network.
2) If you've answered "yes" to 1, how would you tackle this problem from a design viewpoint?
Use a UnitOfWork abstraction. Each UnitOfWork should contain a single entity context. If this is a web app you should have one UnitOfWork per request.
Context lifetime management is a crucial when using ORMs. The entity framework context in keeps information about loaded entities for lazy loading and change tracking purposes and its memory footprint may grow very quickly. If you don't dispose your context you will essentially have a memory leak.
However, you are correct that keeping the context lifetime too short is not ideal since you would probably like to make use of change tracking.
using (var context = new DataContext())
{
context.Products.Add(product);
context.SaveChanges();
}
The above example shows disposes the context too quickly to take advantage of the change tracking goodies.
For Web applications you should use context per request.
For Win Form applications you can dispose of your context when you move from one form to another.
There have been many question on managing EntityContext lifetime,
e.g. Instantiating a context in LINQ to Entities
I've come to the conclusion that the entity context should be considered a unit-of-work and therefore not reused. Great.
But while doing some research for speeding up my database access, I ran into this blog post...
Improving Entity Framework Performance
The post argues that EFs poor performance compared to other frameworks is often due to the EntityConnection object being created each time a new EntityContext object is needed.
To test this I manually created a static EntityConnection in Global.asax.cs Application_Start().
I then converted all my context using statements to
using( MyObjContext currContext = new MyObjeContext(globalStaticEFConnection)
{
....
}
This seems to have sped things up a bit without any errors so far as far as I can tell.
But is this safe?
Does using a applicationwide static EntityConnection introduce race conditions?
Best regards,
Kervin
EntityConnection is documented to be not thread-safe. I think you could pool them, but you cannot use a single, static connection for a Web application, as there will be many threads involved.
If your EF context is Application-wide, consider that user A has made changes (not committed) & user B has committed his changes, all changes will get committed to the database since both user A & B use the same instance
In my project, I did a per WebRequest intance of the EF context - ie. a context object is static from start through end of a web request & all operations in that request work with the same EF context. This has significantly speeded up my processing without the problem mentioned above.
One way to implement this is to use a DI container (I am using Unity) to manage the lifetime of the EF context. The per web request lifetime manager is not given out of the box in Unity, but there are tons of articles out there which show how this can be done.
HTH.
With linq, do you create a single dbContext per request like nHibernate requires (for performance reasons, creating sessions in nhibernate from what I understand are an expensive call).
i.e. in my asp.net-mvc application, I may for a given action, hit the database 5-10 times on seperate calls. Do I need to create a context and re-use it for the entire request?
DataContexts are intended to be used for a single set of actions interacting with your database. I know, that's vague. Their usage is situational. If you are doing related, or specifically sequential activities, then one DataContext is probably good for you. If you are doing unrelated or parallel activities, consider using a DataContext for each activity.
Consider a few guidelines:
Entities retrieved by one DataContext can only be used (read: updated, deleted, etc.) by that same DataContext. If you need to match up objects across separate DataContexts, you'll have to do something such as running a LINQ query to select objects with the same primary key.
LINQ to SQL uses optimistic concurrency.
Dispose of the DataContext when you are done with it (letting it go out of scope and be garbage collected is fine)
Do not use a static or shared DataContext.
When I did a small app using LinqToSql, I found the app was very sluggish when i did a create-use-dispose of a DatabaseContext object each time I had to hit the database.
When I moved to sharing the DBContext across multiple requests... the app suddenly came back to life w.r.t. responsiveness.
Here's a question that I posted which is relevant
I'm new to NHibernate (my 1st big project with it).
I had been using a simple method of data access by creating the ISession object within a using block to do my grab my Object or list of Objects, and in that way the session was destroyed after exiting the code block.
This doesn't work in a situation where lazy-loading is required, however.
For example, if I have a Customer object that has a property which is a collection of Orders, then when the lazy-load is attempted, I get a Hibernate exception.
Anyone using a different method?
Session management:
http://code.google.com/p/dot-net-reference-app/source/browse/trunk/src/Infrastructure/Impl/HybridSessionBuilder.cs
Session per request:
http://code.google.com/p/dot-net-reference-app/source/browse/trunk/src/Infrastructure/Impl/NHibernateSessionModule.cs
check out the SummerOfNHibernate webcasts for a great tutorial... What you're looking for specifically doesn't come until webisode 5 or 6.
Keep your session open for your entire unit of work. If your session is life is too small, you cannot benefit from the session level cache (which is significant). Any time you can prevent a roundtrip to the database is going to save a lot of time. You also cannot take advantage of lazy loading, which is crucial to understand.
If your session lifetime is too big, you can run into other issues.
If this is a web app, you'll probably do fine with the session-per-httpRequest pattern. Basically this is an HttpModule that opens the session at the beginning of the request and flushes/closes at the end. Be sure to store the session in HttpContext.Items NOT A STATIC VARIABLE. <--- leads to all kinds of problems that you don't want to deal with.
You might also look at RhinoCommons for a unit of work implementation.
Since you are developing a Web App (presumably with ASP.NET), check out NHibernate Best Practices with ASP.NET at CodeProject.