I implemented repository pattern to my software by the help of this article. One question boggles my mind. I think Database class should implement singleton pattern because user should not create more than one database context using "var ourDatabase = new Database();" statement. Am i right or is this situation not a criticial issue for usage of the implementation.
You should not have the database context as a singleton with Entity Framework.
For starters, each context instance tracks all changes made to it and "save changes" saves all the changes. So, if you have a web application and you made your context a singleton then all the users would be updating the same context and when one called "save changes" it would save changes for everyone. In a single-user Windows application this is less of an issue, unless you have different parts of the application working in parallel.
Also be mindful that the context caches data it has already loaded and tracks changes by default. In short, this can mean memory bloat and decreased performance as more and more objects are tracked - though in practice the impact of this varies.
From a performance point of view, Entity Framework implements connection pooling underneath the covers so don't worry about creating and disposing database context objects - it is very cheap.
Related
I create instance of context per form and may multi forms use same entity
How handle this when save?
The DbContext is part of your "view state", intended to give you access to the database, hold a copy of the data the user is working on in the Change Tracker, and flush changes back to the database.
In a smart client app the natural scope and lifetime for the DbContext is either global or scoped to a UI element that represents a task or use-case. But in either case you have to prevent the DbContext's Change Tracker from growing too large or from holding on to copies of data too long, as even a single form can stay open all day. A possible rule-of-thumb for these apps is to clear the change tracker after every successful SaveChanges(). Other than that, of course you must avoid long-running transactions so the DbContext doesn't hold a DbConnection open for a long time, but you have to do that anyway. The point is that a DbContext with an empty change tracker can be long-lived.
Using a Short-Lived DbContext is possible, but you loose the services of the Change Tracker and .Local ObservableCollection which make data binding really easy. So that's not a silver bullet.
So on to the question at-hand, if you have DbContext-per-form, and you have form-to-form communication of entities which end up getting saved by a different DbContext, you really have no choice but to disconnect the entities from their home DbContext before sending them over.
Or this might indicate that the two forms really should share a View State, and you should create an explicit View State object that includes the DbContext and the entieies and have both share that between forms.
Take a look at the Model-View-ViewModel (MVVM) pattern which introduces a distinction between the View (form) and the ViewModel, the data that models the use case user's interaction with the app. It's a useful pattern and is very widely used in XAML-based smart clients. Also XAML is (still) the future of smart client apps, so it's useful to learn.
This is basic winform application, no service or anything in-between. I am fetching some records from db using Entity Framework. Below code is in a class called PersonRepository.
var obj = Context.Persons.Where(u=>u.Id==20);
obj.RegisterDate = obj.RegisterDate.ToMountainStandardTime();
return obj;
ToMountainStandardTime is an extension method for date type.
Now after I pull this record, and display to UI. User does some action on screen, And based on requirements insert record in another table called "Activity". User don't need to save anything back in Person table.
After doing their things, like this
Context.Activities.Add(newActivityObject);
Context.SaveChange();
Both methods are in same class. Along with adding a new object in activity table, it also update the register date of selected person class.
I know the reason, this Context object initialize in constructor of PersonRepository class and being used by all the methods in this class.
Most of my experience is using this via restful services where I don't need much to worry about such things because for every request we create new instances of context.
I can simply handle this by Detach the object from context before editing it like this
Context.Entry(obj).State = EntityState.Detached;
But want to know if there is some better way to handle this?
You have a few choices to consider. Firstly, entities either can only be relied upon to be valid within the scope of the DbContext they were read, or they need to be detached and re-attached to transition between DbContext boundaries.
To keep entities scoped within their DbContext, your options are:
Long-lived (i.e. Singleton) DbContext.
Short-lived, project entities to POCO containers and re-load entities on-demand as needed.
The third option is to use short-lived DbContexts, but then manually manage detaching and re-attaching the entities.
I never recommend this third option as it is prone to errors and encourages issues like stale data overwrites. It's neat in concept, but more often than not becomes a repeated source of headaches in practice.
For smaller applications that themselves have relatively short runtime lives, a long-lived DbContext can be a simple to implement option. The biggest negatives of a long-lived DbContext are:
Having a context alive for extended periods of time can mean performance degrades over time as more entities are cached. The assumption that cached entities are better for performance can be misplaced as time to perform operations against entities (updates/inserts) increase as the cache grows, since EF will look through the cache for entity references that might be associated to new/changed entity values.
Data that the context is loading will become stale if multiple instances are running, or external processes can modify data state. By default EF will return cached copies which must manually be reloaded if suspected of being stale.
For larger applications, or long-running applications I would strongly lean towards using short-lived DbContext that rely on POCO ViewModels/DTOs for view-duration data state. This means leveraging Projection via Select or Automapper's ProjectTo to load relevant data from entities on demand to pass to views, then reload entities by ID, and transfer across data or perform actions with changed state values during updates after verifying Row Version Numbers / Timestamps to detect possible stale data state. Reloading an entity and it's related data by PK is extremely quick.
Not only does this avoid the complexity/mess of trying to juggle detached entities, (and reloading data state anyways to guard against stale overwrites) but it can lead to more optimal data read operations and index utilization for many scenarios, especially things like search results which only need a few values from specific tables rather than reading entire entity graphs. A cardinal sin of passing Entities to views is attempting to avoid extra data reads by avoiding eager loading and disabling lazy loading to leave "unused" relationships as #null, or even populating Entity class objects with just a few fields to serve as a view model with .Select which leads to errors or bad assumptions/overwrites in later code. An Entity should always represent a complete (or complete-able) state of the data row. Dual-purposing entities to serve as both data domain state and view state is asking for trouble. Methods expecting an entity should never need to be concerned about whether they are getting a complete entity or a partially complete one.
I'm creating my first application using EntityFramework. I'm using Entity Framework Core and MVVMLight.
I created a DbContext descendant class. I would like to know when to instanciate this DbContext.
My first thought was to create 1 instance for each View.
Imagine the following scenario :
I have an Item class
I create a ItemsViewModel to manage the list of items. In this viewModel, I add a property for the DbContext
When the user double-click an item, it's displayed in a detail view, associated to an ItemViewModel. This view-model also has an instance of my DbContext.
When the user quit the detail view :
If he saved, I update the DbContext of the list
If he canceled, the list doesn't have to be updated
Is this a correct way of doing things ? I've read somewhere that one should have only 1 instance of the DbContext. But in this case every modifications to the detail view are propagated to the list view, even if the detail view was canceled.
Many thanx for listening
Hence you're developing WPF application,you can use a context instance per form.
Here it is from EF Team :
When working with Windows Presentation Foundation (WPF) or Windows
Forms, use a context instance per form. This lets you use
change-tracking functionality that context provides.
I would like to recommend to use repository pattern with Dependency injection (DI).Then you don't need to worry about the instantiation and dispose of the dbcontext. Those are automatic.
Hence you're using EF core, you can use Autofac as a DI API.
Good Article for you : How to work with DbContext
Another good article where it explains how to implement a decoupled, unit-testable, N tier architecture based on Generic Repository Pattern with Entity Framework, IoC Container and Dependency Injection.Yes, this article is for the MVC. But you can get good knowledge of this pattern using this article.
Generic Repository and Unit of Work Pattern, Entity Framework,Autofac
There are tons of articles and SO questions on that, google for "DbContext lifetime desktop application". Also, this MSDN magazine might be helpful, although they discuss the case of nHibernate, rules are exactly the same.
Data Access - Building a Desktop To-Do Application with NHibernate
The recommended practice for desktop applications is to use a session per form, so that each form in the application has its own session. Each form usually represents a distinct piece of work that the user would like to perform, so matching session lifetime to the form lifetime works quite well in practice. The added benefit is that you no longer have a problem with memory leaks, because when you close a form in the application, you also dispose of the session. This would make all the entities that were loaded by the session eligible for reclamation by the garbage collector (GC).
There are additional reasons for preferring a single session per form. You can take advantage of NHibernate’s change tracking, so it will flush all changes to the database when you commit the transaction. It also creates an isolation barrier between the different forms, so you can commit changes to a single entity without worrying about changes to other entities that are shown on other forms.
While this style of managing the session lifetime is described as a session per form, in practice you usually manage the session per presenter.
As for the "1 instance of DbContext", this also is commented there:
A common bad practice with [...] desktop applications is to have a single global session for the entire application.
and reasons are discussed below.
Working on a WPF application using MVVM and powered by Entity Framework. We were very keen to allow users to multi-window this app, for usability purposes. However, that has the potential to cause problems with EF. If we stick to the usual advice of creating one copy of the Repository per ViewModel and someone opens multiple windows of the same ViewModel, it could cause "multiple instances of IEntityChangeTracker" errors.
Rather than go with a Singleton, which has its own problems, we solved this by putting a Refresh method on the repository that gets a fresh data context. Then we do things like this all over the shop:
using (IRepository r = Rep.Refresh())
{
r.Update(CurrentCampaign);
r.SaveChanges();
}
Which is mostly fine. However, it causes problems with maintaining state. If the context is refreshed while a user is working with an object, their changes will be lost.
I can see two ways round this, both of which have their own drawbacks.
We call SaveChanges constantly. This has the potential to slow down the application with constant database calls. Plus there are occasions when we don't want to store incomplete objects.
We copy EF objects into memory when loaded, have the user work with those, and then add a "Save" button which copies all the objects back to the EF object and saves. We could do this with an automapper, but is still seems unnecessary faff.
Is there another way?
I believe having the repository for accessing entity framework as a singleton may not always be wrong.
If you have a scenario were you have a client side repository, i.e. a repository which is part of the executable of the client application, i.e. is used by one client, then a singleton might be ok. Of course I would not use a singleton on the server side.
I asked Brian Noyes (Microsoft MVP) a similar question on a "MVVM" course on the pluralsight website.
I asked: "What is the correct way to dispose of client services which are used in the view model?"
And in his response he wrote: "...most of my client services are Singletons anyway and live for the life of the app."
In addition having a singleton does not prevent you from writing unit tests, as long as you have an interface for the singleton.
And if you use a dependency injection framework (see Marks comment), which is a good idea for itself, changing to singleton instantiation is just a matter of performing a small change in the setup of the injection container for the respective class.
I have a WPF application and am using entity framework. I was reading the tutorial
and the author was talking about disconnected entities, which is the first time I have heard of them. I am a little confused as to when disconnected entities are actually needed, as I have been using EF just fine to do CRUD operations on my business objects. If I am using the same context when I am doing CRUD operations on a business object, why do I need to ever manually track the entity state changes? Thanks for any help.
If you are always keeping around the originating context instance, then you probably do not need to worry about disconnected entities. Disconnected entities often come up in the context of web services or web sites, where the context from which an entity was originally retrieved (and, for example, placed into a Session) is no longer available some time down the road when that entity has been modified and needs to be saved back to the database.