I have a situation where I need to retrieve data from a query which executes for almost half a minute and bring it to a web page. (There is no way to reduce this time because the maximum amount of optimization has been performed on it)
I use a four layer architecture along with Entity Framework ( EF, Data Access Layer, Biz Logic Layer, UI) for my application.
I'm trying to use the singleton method when an instance to the DAL is created (The DAL in turn retrieves data from the database) so that I will be able to re-use this instance and hence additional instances wont be created within the same session.
How do I go about setting the session state and checking the availability of the instance in the State Server?
public static Singleton getInstance() {
if (**instance == null**)
instance = new Singleton();
return instance;
}
What should reside within the if block? What condition should I check for in the if block? I'm really unsure as to what I must do.
PS: This session must have a timeout of 5 mins. I hear this can be specified in the Web.config file. is it true?
To be honest you should rather use Entity Framework context and create it every time you need access to database, i.e. in each method. It is optimized to be used that way. Connection pooling will make sure there is not penalty in recreating EF context each time. This is the best practice.
But your DAL might be more than just simple DB access. If you want to have it as a singleton separate for each session you must create the instance on the first request, store it into the Session and check if it's there before using. With thread safety the code could look like that:
class DALClass
{
private static object instanceLock = new object();
public static DALClass Instance
{
get
{
if (Session["DALInstance"] == null)
{
lock (instanceLock)
{
if (Session["DALInstance"] == null)
{
Session["DALInstance"] = new DALClass();
}
}
}
return (DALClass)Session["DALInstance"];
}
}
}
It sounds to me like you have a well defined architecture which would suit dependency injection. Using DI you could just get your IOC container to return you a singleton object or a transient one. However, be very careful using singletons in a web environment as they often cause more trouble than they are worth.
If the query you are running contains user specific data then I would probably place the results of that query into session within the code which composes the UI part of your application if you are using a pattern like MVC that would be in the controller or MVP in the presenter.
If these patterns aren’t in use then you could consider placing the information into session inside the business layer but only if you wrap up the session and inject in that dependency into your business object, e.g. something like “IUserSession”. The business project should not contain a reference to “system.Web” or anything like that.
Related
In the Business Logic Layer of an Entity Framework-based application, all methods acting on DB should (as I've heard) be included within:
using(FunkyContainer fc = new FunkyContainer())
{
// do the thing
fc.SaveChanges();
}
Of course, for my own convenience often times those methods use each other, for the sake of not repeating myself. The risk I see here is the following:
public void MainMethod()
{
using(FunkyContainer fc = new FunkyContainer())
{
// perform some operations on fc
// modify a few objects downloaded from DB
int x = HelperMethod();
// act on fc again
fc.SaveChanges();
}
}
public int HelperMethod()
{
using(FunkyContainer fc2 = new FunkyContainer())
{
// act on fc2 an then:
fc2.SaveChanges();
return 42;
}
}
I doesn't look good to me, when the container fc2 is created, while fc is still open and has not been saved yet. So this leads to my question number one:
Is having multiple containers open at the same time and acting on them carelessly an acceptable practice?
I came to a conclusion, that I could write a simple guard-styled object like this:
public sealed class FunkyContainerAccessGuard : IDisposable
{
private static FunkyContainer GlobalContainer { get; private set; }
public FunkyContainer Container // simply a non-static adapter for syntactic convenience
{
get
{
return GlobalContainer;
}
}
private bool IsRootOfHierarchy { get; set; }
public FunkyContainerAccessGuard()
{
IsRootOfHierarchy = (GlobalContainer == null);
if (IsRootOfHierarchy)
GlobalContainer = new FunkyContainer();
}
public void Dispose()
{
if (IsRootOfHierarchy)
{
GlobalContainer.Dispose();
GlobalContainer = null;
}
}
}
Now the usage would be as following:
public void MainMethod()
{
using(FunkyContainerAccessGuard guard = new FunkyContainerAccessGuard())
{
FunkyContainer fc = guard.Container;
// do anything with fc
int x = HelperMethod();
fc.SaveChanges();
}
}
public int HelperMethod()
{
using(FunkyContainerAccessGuard guard = new FunkyContainerAccessGuard())
{
FunkyContainer fc2 = guard.Container;
// do anything with fc2
fc2.SaveChanges();
}
}
When the HelperMethod is called by MainMethod, the GlobalContainer is already created, and its used by both methods, so there is no conflict. Moreover, HelperMethod can be also used separately, and then it creates its own container.
However, this seems like a massive overkill to me; so:
Has this problem been already solved in form of some class (IoC?) or at least some nice design pattern?
Thank you.
Is having multiple containers open at the same time and acting on them carelessly an acceptable practice?
Generally this is perfectly acceptable, sometimes even necessary, but you have to be caucious with that. To have multiple containers at the same time is especially handy when doing multithreading operations. Because of how db works generally each thread should have its own DbContext that should not be shared with other threads. Downside to using multiple DbContext at the same time is that each of them will use separate db connection, and sometimes they are limited, what may lead to application occasionally being unable to connect to database. Other downside is the fact that entity generated by one DbContext may not be used with entity generated by other DbContext. In your example HelperMethod returns primitive type, so this is perfectly safe, but if it would return some entity object that in MainMethod you would like to assign for instance to some navigation property of entity created by MainMethod DbContext then you will receive an exception. To overcome this in MainMethod you would have to use Id of entity returned by HelperMethod to retrieve that entity once more, this time with fc context. On the other hand there is an advantage of using multiple contexts - if one context have some troubles, for instance it tried to save something that violated index constaint, then all next trials of saving changes will result in the same exception as the faulty change will still be pending. If you use multiple DbContexts then if one would fail, then second will operate independently - this is why DbContexts should not live long. So generally I would say the best usage rule would be:
Each thread should use a separate DbContext
All methods that executes on the same thread should share the same DbContext
Of course the above applies if the job to be done is short. DbContext should not live long. The best example would be web applications - there each server request is handled by separate thread and the operations to generate response generally do not take long. In such case all methods executed to generate one response should share for convenience the same DbContext. But each request should be served by separate DbContext.
Has this problem been already solved in form of some class (IoC?) or at least some nice design pattern?
What you need to assure is that your DbContext class is singleton per thread, but each thread has its own instance of that class. In my opinion best way to assure this is with IoC. For instance in Autofac in web applications I register my DbContext with the following rule:
builder
.RegisterType<MyDbContext>()
.InstancePerHttpRequest();
This way autofac IoC generates one DbContext per request and share existing instance within the request serving thread. You do not need to care here for disposing your DbContext. Your IoC will do this when your thread is over.
Working in multiple connections at the same time is not the right approach most of the time because:
You can get distributed deadlocks that SQL Server cannot resolve.
You might not see data that was previously written but not yet committed.
You can't share entities across context boundaries (here: methods).
More resource usage.
No ability to transact across context boundaries (here: methods).
These are very severe disadvantages. Usually, the best model is to have one context, connection and transaction for the request that the app is processing (HTTP or WCF request). That's very simple to set up and avoids a lot of issues.
EF is supposed to be used as a live object model. Do not cripple it by reducing it to CRUD.
static FunkyContainer GlobalContainer
That does not work. You shouldn't share a context across requests. Super dangerous. Consider storing a context in HttpContext.Items or whatever is the per-request store in your app.
Thanks for looking.
Background
In my .NET applications I usually have a Business Logic Layer (BLL) containing my business methods and a Data Access Layer (DAL) which contains my Entitiy classes and any methods for dealing with atomic entities (i.e. CRUD methods for a single entity). This is a pretty typical design pattern.
Here is a pseudocode example of what I mean:
BLL
public static int CreateProduct(ProductModel product){
return DAL.SomeClass.CreateProduct(new DAL.Product{
Name = product.Name,
Price = product.Price
});
}
DAL
public int CreateProduct(Product p){
var db = new MyDataContext();
db.Products.AddObject(p);
db.SaveChanges();
return p.Id;
}
No problems with this simple example.
Ideally, all the business of instantiating a data context and using that data context lives in the DAL. But this becomes a problem if I attempt to deal with slightly more complex objects:
BLL
public static int CreateProduct(ProductModel product){
return DAL.SomeClass.CreateProduct(new DAL.Product{
Name = product.Name,
Price = product.Price,
ProductType = DAL.SomeClass.GetProductTypeById(product.ProductTypeId) //<--PROBLEM
});
}
Now, instead of saving the entity, I get the following error:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
Ok, so the answer to dealing with that is to pass a common data context to both calls:
BLL
public static int CreateProduct(ProductModel product){
using{var db = new DAL.MyDataContext()){
return DAL.SomeClass.CreateProduct(new DAL.Product{
Name = product.Name,
Price = product.Price,
ProductType = DAL.SomeClass.GetProductTypeById(product.ProductTypeId, db) //<--CONTEXT
}, db); //<--CONTEXT
}
}
Problem
This solves the immediate problem, but now my referential transparency is blown because I have to:
Instantiate the data context in the BLL
Pass the data context to the DAL from the BLL
Create overridden methods in the DAL that accept a data context as a parameter.
This may not be a problem for some but for me, since I write my code in a more functional style, it is a big problem. It's all the same database after all, so why the heck can't I deal with unique entities regardless of their data context instance?
Other Notes
I realize that some may be tempted to simply say to create a common data context for all calls. This won't fly as doing so is bad practice for a multitude of reasons and ultimately causes a connection pool overflow. See this great answer for more details.
Any constructive input is appreciated.
Personally, I track my unit of work and associate a data context to it via static methods. This works great if you aren't talking about operations with long lifetimes, such as my current project, an ASP.NET application, where every request is a (mostly) distinct unit and a request start and end coincide with the unit start/end. I store data context in the request CurrentContext, which, if you aren't familiar with it, is basically a dictionary managed by the system that allocates a request-specific storage accessible by static methods. The work's already done for me there, but you can find lots of examples of implementing your own unit of work pattern. One DbContext per web request... why?
Another equally workable answer for many is injection. Used for this purpose (injecting datacontext), it basically mimics the code you wrote at the end of your question, but shields you from the "non-functional" stuff you dislike.
Yes, you are only accessing one database, but if you look closely, you will see the database is not the constraint here. That is arising from the cache, which is designed to permit multiple, differing, concurrent copies of the data. If you don't wish to permit that, then you have a whole host of other solutions available.
I have this code in my Controller:
public class MyController : Controller
{
private readonly IMyRepository myRepository;
public MyController() : this(new MyRepository())
{}
public MyController(IMyRepository myRepository)
{
this.myRepository = myRepository;
}
public ActionResult Index()
{
return View(myRepository.GetData());
}
}
MyRepository uses EF for data operations. Every time user loads this page instance of MyRepository is creating. That means EF context is creating and Fluent API code is executing (OnModelCreating method).
Are there any possibilities not to create EF context everytime when user loads the page?
MyRepository uses EF for data operations. Every time user loads this
page instance of MyRepository is creating. That means EF context is
creating and Fluent API code is executing (OnModelCreating method).
You're wrong. Put a breakpoint on your OnModelCreating method. This method will only get hit once, when your application loads. It will hit the breakpoint again if you rebuild the project, because this causes the binary dll to be reloaded into the app domain. However if you leave the application running and hit the controller action twice (without rebuilding in between), you will see that OnModelCreating does NOT get hit the second time. Like Serg Rogovtsev says, EF caches the model (meaning the schema) after it is created during OnModelCreating.
The only objection I have to Serg Rogovtsev's answer is that I would never create a singleton instance of the DbContext. Instead you should use one instance per HttpContext (a.k.a. per web request). If you use it as a singleton, and you have concurrency enabled, you would end up seeing DbConcurrencyExceptions creep up in your app. Use DI/IoC, and create/dispose the DbContext instance at the beginning/end of the request response cycle. That is the best practice. Don't worry about the overhead of creating a new MyDbContext() instance. After EF initializes (warms up) during the first construction, future constructions will be fairly cheap.
To answer your question: you can create a singleton of your repository or you can use DI container which will hold single instance for you.
But to the point: if you set breakpoint inside OnModelCreating you will find that it gets called only once per application instance. EntityFramework uses pretty effective model caching. So you don't have to worry about performance hit caused by creation of EF contexts.
Change your controller so you create an instance of your repository in a lazy way. You can use the Lazy < T > class for example.
In terms of performance I'd favour looking to persist data and not the context, the EF context is optimized to be created and then disposed to free up connections in the pool.
Some other EF performance methods at http://www.sql-server-performance.com/2012/entity-framework-performance-optimization/
Best practice is to dispose the EF context after you've retrieved/updated your data.
In my DALs I currently use a new DataContext instance for each method, i.e. create the context for each data call, then dispose it (with using). I remember I read that was sort of a best practice.
Now I think that I probably better use one common DataContext per DAL which will require less lines to write and will allow to update changes in the database without attaching the entities to the newly created context.
But I am not sure whether this will impact the productivity of the application. Are there negative things which may appear with this new approach, like maybe "each context reserves a connection line with a database" or "there are only a limited number of contexts available per application"?
From what I read and my own conclusion, the basic rule is: use a single DataContext instance for each short time set of operations, this means:
Use new (separate) instance of DataContext for each operation (transaction) in long living parent objects, such as DALs. For example, the main form has a DAL which uses a DataContext, the main form is the most long living object in a desktop application, thus having a single instance of a DataContext to serve all the main form data operations will not be a good solution due to the increasing cache and risk of the data to become obsolete.
Use single (common) instance of DataContext for all operations in short time living parent objects. For example, if we have a class which executes a set of data operations in a short amount of time, such as takes data from a database, operates with them, updates them, saves the changes to the database and gets disposed, we better create one single instance of the DataContext and use it in all the DAL methods. This relates to a web applications and services as well since they are stateless and are being executed per request.
Example of when I see a requirement of a common DataContext:
DAL:
// Common DAL DataContext field.
DataContext Context = new DataContext();
public IEnumerable<Record> GetRecords()
{
var records = Context.Records;
foreach (var record in records)
{
yield return record;
}
}
public void UpdateData()
{
Context.SaveChanges();
}
BLL:
public void ManageData()
{
foreach (var record in DAL.GetRecords())
{
record.IsUpdated = true;
DAL.UpdateData();
}
}
With this approach you will end up with a lot of objects created in memory (potentially, the whole db) and (which can be even more important), those objects will not correspond to current values in the db (if the db gets updated outside of your application/machine). So, in order to use memory efficiently and to have up-to-data values for your entities, it's really better to create data context per transaction.
I have a number of static methods that perform simple operations like insert or delete a record. All these methods follow this template of using:
public static UserDataModel FromEmail(string email)
{
using (var db = new MyWebAppDataContext())
{
db.ObjectTrackingEnabled = false;
return (from u in db.UserDataModels
where u.Email == email
select u).Single();
}
}
I also have a few methods that need to perform multiple operations that use a DataContext:
public static UserPreferencesDataModel Preferences(string email)
{
return UserDataModel.Preferences(UserDataModel.FromEmail(email));
}
private static UserPreferencesViewModel Preferences(UserDataModel user)
{
using(var db = new MyWebAppDataContext())
{
var preferences = (from u in db.UserDataModels
where u == user
select u.Preferences).Single();
return new UserPreferencesViewModel(preferences);
}
}
I like that I can divide simple operations into faux-stored procedures in my data models with static methods like FromEmail(), but I'm concerned about the cost of having Preferences() invoking two connections (right?) via the two using DataContext statements.
Do I need to be? Is what I'm doing less efficient than using a single using(var db = new MyWebAppDataContext()) statement?
If you examine those "two" operations, you might see that they could be performed in 1 database roundtrip. Minimizing database roundtrips is a major performance objective (second to minimizing database io).
If you have multiple datacontexts, they view the same record differently. Normally, ObjectTracking requires that the same instance is always used to represent a single record. If you have 2 DataContexts, they each do their own object tracking on their own instances.
Suppose the record changes between DC1 observing it and and DC2 observing it. In this case, the record will not only have 2 different instances, but those different instances will have different values. It can be very challenging to express business logic against such a moving target.
You should definately retire the DataContext after the UnitOfWork, to protect yourself from stale instances of records.
Normally you should use one context for one logical unit of work. So have a look at the unit of work pattern, ex. http://dotnet.dzone.com/news/using-unit-work-pattern-entity
Of cause there is some overhead in creating a new DataContext each time. But its a good practice to do as Ludwig stated: One context per unit of work.
Its using connection pooling so its not a too expensive operation.
I also think creating a new DataContext each time is the correct way but this link explains different approaches for handling the data context. Linq to SQL DataContext Lifetime Management
I developed a wrapper component that uses an interface like:
public interface IContextCacher {
DataContext GetFromCache();
void SaveToCache(DataContext ctx);
}
And use a wrapper to instantiate the context; if it exists in cache, it's pulled from there, otherwise, a new instance is created and pushed to the Save method, and all future implementations would get the value from the getter.
Depending on the type of application would be the actual caching mechanism. Say for instance, an ASP.NET web application. This could store the context in the items collection, so its alive for the request only. For a windows app, it could pull it from some singleton collection. It could be whatever you wanted under the scenes.