I have read all sorts of posts on this subject but couldn't find the answer to my question.
The general consensus is that I should be creating a context for 1 unit of work (say 1 web page). I have enclosed every method in my Database.cs (see below) with 'using' hence to me - that implies that each time a method from this class is called - a context is created. So if I was to call 2 Methods from Database.cs from the same Action in the HomeController.cs - would that mean that 2 contexts are created?
Would it not be better to declare a private field inside Database.cs like so:
private Entities db = new Entities()
And have each method within the Database.cs class access it? Which approach is the best?
My current implementation (I'm only going to include the method Verify but there are many methods in the Database class):
HomeController.cs
[AllowAnonymous]
public class HomeController : Controller
{
private IDatabase Database;
public HomeController()
{
this.Database = new Database();
}
[HttpGet]
public ActionResult Verify(string id)
{
if (Database.VerifyUser(id))
{
return View();
}
else
{
ViewBag.Error = "There was an error with the verification process";
return View();
}
}
}
Database.cs
public class Database : IDatabase
{
... some other methods ...
public bool VerifyUser(string verificationHash)
{
using (Entities db = new Entities())
{
var userToVerify = db.VerifyUser(verificationHash);
int count = userToVerify.Count();
if (count == 1)
{
return true;
}
else
{
return false;
}
}
}
}
db.VerifyUser(..) - this is a call to a stored procedure
Yes that means there are two instances of DbContext.
The better is to have one instance of DbContext in your Database class and use this instance in all your methods.
public class Database : IDatabase, IDisposeable
{
private Entities db;
public Database()
{
db = new Entities()
}
... some other methods ...
public bool VerifyUser(string verificationHash)
{
var userToVerify = db.VerifyUser(verificationHash);
int count = userToVerify.Count();
if (count == 1)
{
return true;
}
else
{
return false;
}
}
public void Dispose()
{
db.Dispose()
}
}
Then when you finish from Database instance you dispose it and it will dispose the DbContext
public class HomeController : Controller
{
private IDatabase Database;
public HomeController()
{
this.Database = new Database();
}
[HttpGet]
public ActionResult Verify(string id)
{
using(this.Database)
{
if (Database.VerifyUser(id))
{
return View();
}
else
{
ViewBag.Error = "There was an error with the verification process";
return View();
}
}
}
}
BTW: you may prefer to dispose your resources at the controller level. In that case, you don't need to add using statement in your actions
e.g. add this to your controller:
protected override void Dispose(bool disposing)
{
this.Database.Dispose();
base.Dispose(disposing);
}
Yes in your design DbContext created and disposed in every method calls.
Actually, it is not a good solution to put all database operations to a class and create DbContext over and over again. You probably have a problem in future with that class. It might have hundred methods in time and so it is hard to maintain and all entities are not related with each other semantically so it may cause confusion. I think it is a better solution to seperate entity types into classes. For example, you have an users, projects, departments. If we apply my solution to these entities then the uml class diagram will be like this.
All repositories takes a reference to DbContext. It is called Dependency Injection. It means that dbcontext is instantiated once and passes its reference through necessary repositories so there are no context re-creation. Also there is a generic repository which you can put standard procedures.
So you can use repositories like this.
[HttpGet]
public ActionResult Verify(string id){
using(var context = new DbContext())
{
var userRepo = new UserRepository(context);
//Department repository can be used over the same context.
var departmentRepo = new DepartmentRepository(context);
if(userRepo.verifyUser(id)){
return View();
}
}
}
Related
Question:
Why does passing a list from a protected internal class to an API method and then back to my UI take 4 seconds when direct data access in Entity takes .4? Is it due to the actual passing of the list through these methods?
Background:
I wish to create an "API" layer that sits between my data access layer using Entity Framework and my UI layer. The idea is to limit access to the CRUD operations and force everything through the API however I'm noticing terrible performance.
When I use my class structure here, the get method in this case takes 4 seconds to run:
public class API
{
DataAccessClass _dataAccess = new DataAccessClass();
public List<Items> GetById(int id)
{
return _dataAccess.Get(id);
}
protected internal class DataAccessClass
{
protected internal List<Items> GET(int id)
{
using (var context = dbcontext)
{
return context.GetItems();
}
}
protected internal List<Items> GET(long id)
{
using (var context = dbcontext)
{
return context.GetItems();
}
}
}
}
However when I use my dbcontext directly in code (which I want to prevent), it runs in .4 seconds using the same code found in the protected class above:
using (var context = dbcontext)
{
return context.GetItems();
}
EDIT:
When I exclude the data access portion of the API which is the protected internal portion, and run the using statement in the API directly (just cutting out the protected internal portion) then I get the acceptable .4 seconds.
To solve my performance issue, I removed overloads from the GET class above.
My performance issues from the original question where resolved by changing method names on two of my get methods (one that took an int and one long). Not sure why these overloads causes issues but by removing the overloads and specifying names directly, my issue with performance was resolved.
My working class looks like:
public class API
{
DataAccessClass _dataAccess = new DataAccessClass();
public List<Items> GetById(int id)
{
return _dataAccess.Get(id);
}
protected internal class DataAccessClass
{
protected internal List<Items> GetByInt(int id)
{
using (var context = dbcontext)
{
return context.GetItems();
}
}
protected internal List<Items> GetByLong(long id)
{
using (var context = dbcontext)
{
return context.GetItems();
}
}
}
}
I've setup an API that has a simple getCustomers() method. The endpoint returns data on the first call, but returns an error on a second call.
Error: The operation cannot be completed because the DbContext has been disposed
The error is caused within my CustomerService on the return db.Customers...
Question: Why does this work on the first call, but fail on the second call. How can this be resolved?
GitHub Repo can be found here: https://github.com/ChaseHardin/MyBookStore
Here's a walkthrough of the code:
Controller:
[RoutePrefix("api/customers")]
public class CustomerController : ApiController
{
private readonly CustomerService _service = new CustomerService();
[HttpGet, Route("")]
public virtual IHttpActionResult Get()
{
var customers = _service.GetCustomers();
return Ok(new {customers});
}
}
Customer Service:
public class CustomerService : BaseService
{
public List<CustomerViewModel> GetCustomers()
{
using (var db = Application.GetDatabaseInstance())
{
return db.Customers.Select(AutoMapper.Mapper.Map<CustomerViewModel>).ToList();
}
}
}
BaseService
public class BaseService
{
public BaseService()
{
AutoMapperConfiguration();
}
public void AutoMapperConfiguration()
{
Assembly.GetExecutingAssembly()
.GetTypes()
.Where(x => x.IsClass && x.Namespace == "MyBookStore.Business.ViewModels")
.ForEach(x => System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(x.TypeHandle));
AutoMapper.Mapper.CreateMap<bool, short?>().ConvertUsing(x => x ? (short)1 : (short)0);
AutoMapper.Mapper.CreateMap<short, bool>().ConvertUsing(x => x == 1);
AutoMapper.Mapper.CreateMap<bool, int?>().ConvertUsing(x => x ? 1 : 0);
AutoMapper.Mapper.CreateMap<int?, bool>().ConvertUsing(x => x.HasValue && x.Value == 1);
AutoMapper.Mapper.CreateMap<short, int>().ConvertUsing(x => (int)x);
AutoMapper.Mapper.CreateMap<int, int?>().ConvertUsing(x => x);
}
}
CustomerViewModel
public class CustomerViewModel
{
static CustomerViewModel()
{
AutoMapper.Mapper.CreateMap<Customer, CustomerViewModel>().ReverseMap();
}
public Guid CustomerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Context Setup:
public class Application
{
private static readonly MyBookStoreEntity Context = new MyBookStoreEntity();
public static MyBookStoreEntity GetDatabaseInstance()
{
return Context;
}
}
When you use a using block:
using (var db = Application.GetDatabaseInstance())
The object being "used" will be disposed at the end of the block. (using is basically syntactic shorthand for a try/finally where the finally block calls .Dispose() on the object.)
And what you're "using" is this value:
private static readonly MyBookStoreEntity Context = new MyBookStoreEntity();
This value is static, so it's the same instance of MyBookStoreEntity every time it's called. But when you call it the first time, you .Dispose() it. So any subsequent calls will be on a disposed object.
Basically, you've discovered one of the reasons why a static database context is a very bad idea. You can still encapsulate your database context into a method like you have, but make the method return a new instance each time:
public static MyBookStoreEntity GetDatabaseInstance()
{
return new MyBookStoreEntity();
}
Or, if that method isn't really providing any benefit at this point, then just create the context where you need it:
using (var db = new MyBookStoreEntity())
Creating a database context isn't a particularly heavy operation. But keeping them around when you're not using them is. (And sharing them among different operations is fraught with peril.) A good rule of thumb is to discretely define the database operations you need to perform for a given application operation, and to create/use/dispose your database connection in as tight a code block around those operations as possible.
I'm using ASP 5, MVC 6, and Entity Framework 7 to create a small website (foreseeably less than 100 registered users and 10,000 monthly visitors). I'm a rookie programmer with under 1000 hours of combined experience and research.
I've got a lot of questions at the bottom, but in general I'd just like to be sure I understand the repository pattern and why it could be beneficial to me. Right now I'm only using it because I read 'it's good idea' from multiple sources, and because it seems to make sense for organizational purposes.
After I read about the Repository Pattern. I took some ideas from these sources:
Microsoft, Code Guru, DotNetCurry
I created a generic interface IRepository:
interface IRepository<TEntity,in TPKey> where TEntity : class
{
IEnumerable<TEntity> GetAll();
TEntity Get(TPKey id);
void Insert(TEntity ent);
void Update(TEntity ent);
void Delete(TEntity ent);
}
Then I created a specific Repository for one of my entities:
public class CollegeRepository : IRepository<Models.College, int>
{
private ApplicationDbContext _context = null;
public CollegeRepository()
{
_context = new ApplicationDbContext();
}
public CollegeRepository(ApplicationDbContext context)
{
this._context = context;
}
public College Get(int id)
{
return _context.Colleges.Where(c => c.CollegeID == id).FirstOrDefault();
}
public IEnumerable<College> GetAll()
{
return _context.Colleges.ToList();
}
public void Insert(College college)
{
_context.Colleges.Add(college);
}
public void Update(College college)
{
_context.Update(college);
}
public void Delete(College college)
{
_context.Colleges.Remove(college);
}
Inside of my CollegesController I originally did something like this:
// POST: Schools/Edit/5
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public IActionResult Edit(College school, IFormFile logo)
{
if (ModelState.IsValid)
{
if (logo != null)
{
byte[] imgBytes = new byte[logo.Length];
logo.OpenReadStream().Read(imgBytes, 0, (int)logo.Length);
school.Logo = imgBytes;
_context.Update(school);
}
else
{
// Mark the logo as unmodified so the data is not lost.
_context.Update(school).Property(s => s.Logo).IsModified = false;
}
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(school);
}
Then changed to this:
// POST: Schools/Edit/5
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public IActionResult Edit(College school, IFormFile logo)
{
if (ModelState.IsValid)
{
collegeRepo.Update(school, logo);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(school);
}
And modified the specific repository to add an Update overload:
public class CollegeRepository : IRepository<Models.College, int>
{
public void Update(College college)
{
_context.Update(college);
}
public void Update(College college, IFormFile logo)
{
if (logo != null)
{
byte[] imgBytes = new byte[logo.Length];
logo.OpenReadStream().Read(imgBytes, 0, (int)logo.Length);
college.Logo = imgBytes;
_context.Update(college);
}
else
{
// Mark the logo as unmodified so the data is not lost.
_context.Update(college).Property(s => s.Logo).IsModified = false;
}
}
}
It seems I have successfully separated my logic from my controller. Is this the idea behind the repository pattern? Have I used it successfully in this example? To what degree am I unsuccessful?
I was reading, after I did all this, that the repository pattern is not all that useful for projects which will only use (and may only ever use) 1 data source (like mine), but that there should always be some sort of Unit of Work class to keep logic out of controllers (I vaguely understand what it means to have a unit of work, but answers that touch on this would be appreciated as well).
I've also read that the repository pattern is helpful for reducing duplicate code. I can't see far enough ahead, with my inexperienced eyes, to think that I might use any of my controller code again. What are some common MVC scenarios where you've seen (could see) code duplication occur without the repository pattern?
The way I am utilising the MVC pattern at the moment in my ASP.NET application (using Entity Framework) is as follows:
1) My Models folder contains all EF entities, as well as my ViewModels
2) I have a Helpers folders where I store classes created for the purposes of the particular application.
3) In my Helpers folder, I have a static class named MyHelper which contains methods that access the DB using EF.
namespace myApp.Helpers
{
public static class MyHelper
{
public static async Task<ProductVM> GetProductAsync(int productId)
{
using (var context = new myEntities())
{
return await context.vwxProducts.Where(x => x.ProductId == productId).Select(x => new ProductVM { A = x.A, B = x.B }).FirstOrDefaultAsync();
}
}
}
}
4) My controllers then call these functions where necessary:
namespace myApp.Controllers
{
public class ProductController : Controller
{
[HttpGet]
public async Task<ActionResult> Index(int productId)
{
var productVM = await MyHelper.GetProductAsync(productId);
return View(productVM);
}
}
}
I usually encounter comments in SO of the type "don't use a static class, static classes are evil, etc". Would this apply in such a scenario? If yes, why? Is there a better 'structure' my app should follow for best practices and for avoiding such pitfalls?
You can't really use a static class for this. Your Entity Framework context should have one and only one instance per request. Your methods here instantiate a new context for each method, which is going to cause a ton of problems with Entity Framework.
The general concept is fine, but your MyHelper class should be a normal class. Add a constructor that takes an instance of your context, and then use a DI container to inject the context into the helper class and the helper class into your controller.
UPDATE
Helper
namespace myApp.Helpers
{
public class MyHelper
{
private readonly DbContext context;
public MyHelper(DbContext context)
{
this.context = context;
}
public async Task<ProductVM> GetProductAsync(int productId)
{
return await context.vwxProducts.Where(x => x.ProductId == productId).Select(x => new ProductVM { A = x.A, B = x.B }).FirstOrDefaultAsync();
}
}
}
Controller
namespace myApp.Controllers
{
public class ProductController : Controller
{
private readonly MyHelper myHelper;
public ProductController(MyHelper myHelper)
{
this.myHelper = myHelper;
}
[HttpGet]
public async Task<ActionResult> Index(int productId)
{
var productVM = await myHelper.GetProductAsync(productId);
return View(productVM);
}
}
}
Then, you just need to set up a DI container to inject everything. The code for that is entirely dependent on which container you end up going with, so I can't really help you further. It's usually pretty straight-forward, though. Just read the docs for the container. You'll want to set the life-time scope of your objects to the request. Again, it's different for different containers, but they'll all have some sort of request-scope.
I was thinking to add comment to ChrisPratt's answer, but it ended being too long, so let me add separate answer.
Basically, this is not a life/death choice. Sure, static methods are not as flexible as classes for db access. But they are not bad per-se. One DbContext per request is a something to aim for. It is not an absolute must. It is kinda like dependency injection - you get more flexibility and in turn increase code complexity.
Look at these three questions and their answers, by taking into account everything they say, I'm sure you'll be able to answer your question yourself:
Why would I use static methods for database access
When to use static classes in C#
One DbContext per web request... why?
EDIT: Chris left good comment on my answer and I've changed answer a bit to take into account what he said.
Your idea is correct and I use it always. But the style is like this:
1) For each entity (i.e User) we have a static class inside Providers folder. In this class we can do general methods (i.e create, Get, GetAll , ..)
public static class Users
{
public static IEnumerable<kernel_Users> GetAll()
{
Kernel_Context db = new Kernel_Context();
return db.kernel_Users;
}
public static kernel_Users Get(int userId)
{
Kernel_Context db = new Kernel_Context();
return db.kernel_Users.Where(c => c.UserId == userId).FirstOrDefault();
}
...
}
2) We have another class that is not static.It is inside Models folder. This is the place that we can access to an instance of the entity :
public partial class kernel_Users
{
[Key]
public int UserId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
[NotMapped]
public string FullName
{
get
{
return FirstName + " " + LastName;
}
}
public bool Delete(out string msg)
{
...
}
...
}
I use a static class that has the context injected into a static constructor for the purposes of loading a cache of data that rarely changes. And it (should) be thread safe. I hope this helps you, it's very handy in my experience:
public static class StaticCache<T> where T: class
{
private static List<T> dbSet;
public static Dictionary<string, List<T>> cache = new Dictionary<string, List<T>>();
private static readonly object Lock = new object();
public static void Load(DbContext db, string connStr, string tableName)
{
lock (Lock)
{
try
{
if (connStr != null)
{
using (db)
{
dbSet = db.Set<T>().ToList();
cache.Add(tableName, dbSet);
}
}
}
catch { }
}
}
}
void Testit()
{
var context = new YourContextSubClass(connStr);
StaticCache<TableEntity>.Load(context, connstr, "tableEntityNameString");
}
Creating a new MVC project and like the idea of repositories in the data layer, so i have implemented them. I have also created a Service layer to handle all business logic and validation, this layer in turn uses the appropriate repository. Something like this (I am using Simple Injector to inject)
DAL LAYER
public class MyRepository {
private DbContext _context;
public MyRepository(DbContext context) {
_context = context;
}
public MyEntity Get(int id)
{
return _context.Set<MyEntity>().Find(id);
}
public TEntity Add(MyEntity t)
{
_context.Set<MyEntity>().Add(t);
_context.SaveChanges();
return t;
}
public TEntity Update(MyEntity updated, int key)
{
if (updated == null)
return null;
MyEntity existing = _context.Set<MyEntity>().Find(key);
if (existing != null)
{
_context.Entry(existing).CurrentValues.SetValues(updated);
_context.SaveChanges();
}
return existing;
}
public void Delete(MyEntity t)
{
_context.Set<MyEntity>().Remove(t);
_context.SaveChanges();
}
}
SERVICE LAYER
public class MyService {
private MyRepository _repository;
public MyService(MyRepository repository) {
_repository = repository;
}
public MyEntity Get(int id)
{
return _repository.Get(id);
}
public MyEntity Add(MyEntity t)
{
_repository.Add(t);
return t;
}
public MyEntity Update(MyEntity updated)
{
return _repository.Update(updated, updated.Id);
}
public void Delete(MyEntity t)
{
_repository.Delete(t);
}
}
Now this is very simple, so i can use the following code to update an object.
MyEntity entity = MyService.Get(123);
MyEntity.Name = "HELLO WORLD";
entity = MyService.Update(entity);
Or this to create an object
MyEntity entity = new MyEntity();
MyEntity.Name = "HELLO WORLD";
entity = MyService.Add(entity);
// entity.Id is now populated
Now say i needed to update an item based on the creation Id of another, i could use the code above all fine, but what happens if an error occurs? I need some sort of transaction/rollback. Is this what the Unit Of Work pattern is suppose to solve?
So i guess i need to have DbContext in my UnitOfWork object, so i create an object like so?
public class UnitOfWork : IDisposable {
private DbContext _context;
public UnitOfWork(DbContext context) {
_context = context;
}
public Commit() {
_context.SaveChanges();
}
public Dispose() {
_context.Dispose();
}
}
Ok so again, thats quite simple. UnitOfWork holds the context as well ( i use same context on all repositories anyway) and it calls the SaveChanges() method. I would then remove the SaveChanges() method call from my repository. So to add i would do the following:
UnitOfWork uow = new UnitOfWork(new DbContext()); // i would inject this somehow
MyEntity entity = new MyEntity();
MyEntity.Name = "HELLO WORLD";
entity = MyService.Add(entity);
uow.Commit();
But what if i need to create an object and then update other objects based on that Id, this will now not work, because the Id will not be created until i call Commit on the uow. Example
UnitOfWork uow = new UnitOfWork(new DbContext()); // i would inject this somehow
MyEntity entity = new MyEntity();
MyEntity.Name = "HELLO WORLD";
entity = MyService.Add(entity);
// entity.Id is NOT populated
MyEntity otherEntity = MyService.Get(123);
otherEntity.OtherProperty = entity.Id;
MyService.Update(otherEntity);
uow.Commit(); // otherEntity.OtherProperty is not linked.....?
So i have a feeling that this UnitOfWork class is not right... maybe i am miss understanding something.
I need to be able to add an entity and get that Id and use it on another entity, but if an error occurs, i want to "rollback" like an ado.net transaction would do.
Is this functionality possible using Entity Framework and Repositories?
I have to say first that there is not a unique right way to solve this issue. I'm just presenting here what I would probably do.
First thing is, DbContext itself implements the Unit of work pattern. Calling SaveChanges does create a DB transaction so every query executed against the DB will be rollbacked is something goes wrong.
Now, there is a major issue in the current design you have: your repository calls SaveChanges on the DbContext. This means that you make XXXRepository responsible to commit all the modification you made on the unit of work, not just the modifications on the XXX entities your repository is responsible for.
Another thing is that DbContext is a repository itself too. So abstracting the DbContext usage inside another repository just creates another abstraction on an existing abstraction, that's just too much code IMO.
Plus the fact you may need to access XXX entities from YYY repository and YYY entities from XXX repository, so to avoid circular dependencies you'll end up with a useless MyRepository : IRepository<TEntity> that just duplicates all the DbSet methods.
I would drop the whole repository layer. I would use the DbContext directly inside the service layer. Of course, you can factor all complex queries you don't want to duplicate in the service layer. Something like:
public MyService()
{
...
public MyEntity Create(some parameters)
{
var entity = new MyEntity(some parameters);
this.context.MyEntities.Add(entity);
// Actually commits the whole thing in a transaction
this.context.SaveChanges();
return entity;
}
...
// Example of a complex query you want to use multiple times in MyService
private IQueryable<MyEntity> GetXXXX_business_name_here(parameters)
{
return this.context.MyEntities
.Where(z => ...)
.....
;
}
}
With this pattern, every public call on a service class is executed inside a transaction thanks to DbContext.SaveChanges being transactional.
Now for the example you have with the ID that is required after the first entity insertion, one solution is to not use the ID but the entity itself. So you let Entity Framework and its own implementation of the unit of work pattern deal with it.
So instead of:
var entity = new MyEntity();
entity = mydbcontext.Add(entity);
// what should I put here?
var otherEntity = mydbcontext.MyEntities.Single(z => z.ID == 123);
otherEntity.OtherPropertyId = entity.Id;
uow.Commit();
you have:
var entity = new MyEntity();
entity = mydbcontext.Add(entity);
var otherEntity = mydbcontext.MyEntities.Single(z => z.ID == 123);
otherEntity.OtherProperty = entity; // Assuming you have a navigation property
uow.Commit();
If you don't have a navigation property, or if you have a more complex use case to deal with, the solution is to use the good gold transaction inside your public service method:
public MyService()
{
...
public MyEntity Create(some parameters)
{
// Encapuslates multiple SaveChanges calls in a single transaction
// You could use a ITransaction if you don't want to reference System.Transactions directly, but don't think it's really useful
using (var transaction = new TransactionScope())
{
var firstEntity = new MyEntity { some parameters };
this.context.MyEntities.Add(firstEntity);
// Pushes to DB, this'll create an ID
this.context.SaveChanges();
// Other commands here
...
var newEntity = new MyOtherEntity { xxxxx };
newEntity.MyProperty = firstEntity.ID;
this.context.MyOtherEntities.Add(newEntity);
// Pushes to DB **again**
this.context.SaveChanges();
// Commits the whole thing here
transaction.Commit();
return firstEntity;
}
}
}
You can even call multiple services method inside a transactional scope if required:
public class MyController()
{
...
public ActionResult Foo()
{
...
using (var transaction = new TransactionScope())
{
this.myUserService.CreateUser(...);
this.myCustomerService.CreateOrder(...);
transaction.Commit();
}
}
}