Entity Framework 5 - multiple DbContext and a Generic Repository class - c#

All,
I'm using Unit Of Work and Generic Repository patterns for data access in my ASP.NET MVC app with Entity Framework 5. My app worked fine when I only had to deal with 1 database and DbContext.
My problem is, I have a second not-very-closely-related database I need data access for, so I'm assuming I need a second DbContext. However, I don't know how to refactor my Generic Repository to accommodate more than one DbContext. Help!
Here's a simplified look at what I'm attempting so with comments explaining what's failing:
public class UnitOfWork
{
private Db1Entities db1Context = new Db1Entities();
private Db2Entities db2Context = new Db2Entities();
public GenericRepository<ObjectA> ObjectARepository { // ObjectA is sourced from database 1, so it uses a different DbContext than ObjectB.
get {
return new GenericRepository<ObjectA>(db1Context);
}
}
public GenericRepository<ObjectB> ObjectBRepository { // ObjectB is sourced from database 2, so it uses a different DbContext than ObjectA.
get {
return new GenericRepository<ObjectB>(db2Context);
}
}
}
public class GenericRepository<T> where T : class
{
internal DbContext context; // This line and the GenericRepository constructor are my problem. Type DbContext, being a base class, doesn't have the db objects that Db1Entities or Db2Entities have.
// When I used to only have to manage 1 DbContext, "context" was type Db1Entities and it worked fine.
internal DbSet<T> dbSet;
public GenericRepository(DbContext context) {
this.context = context;
this.dbSet = context.set<T>();
}
public virtual T GetByID (int id) {
// code to return a T object by id...
}
// Other repository methods...
}
FYI this is what I'm doing to get by for now. I don't consider it a solution because I'm duplicating "GenericRepository" by copying it as 2 generic repositories, each designed for a different DbContext. I think I ought to be able to use "GenericRepository" and be able to pass it a DbContext rather than making a GenericRepository class for each DbContext... I just don't know how to make it work. See below:
public class UnitOfWork
{
private Db1Entities db1Context = new Db1Entities();
private Db2Entities db2Context = new Db2Entities();
public GenericDb1Repository<ObjectA> ObjectARepository { // ObjectA is sourced from database 1, so it uses a different DbContext than ObjectB.
get {
return new GenericDb1Repository<ObjectA>(db1Context);
}
}
public GenericDb2Repository<ObjectB> ObjectBRepository { // ObjectB is sourced from database 2, so it uses a different DbContext than ObjectA.
get {
return new GenericDb2Repository<ObjectB>(db2Context);
}
}
}
public class GenericDb1Repository<T> where T : class
{
internal Db1Entities context;
internal DbSet<T> dbSet;
public GenericRepository(Db1Entities context) {
this.context = context;
this.dbSet = context.set<T>();
}
public virtual T GetByID (int id) {
// code to return a T object by id...
}
// Other repository methods...
}
public class GenericDb2Repository<T> where T : class
{
internal Db2Entities context;
internal DbSet<T> dbSet;
public GenericRepository(Db2Entities context) {
this.context = context;
this.dbSet = context.set<T>();
}
public virtual T GetByID (int id) {
// code to return a T object by id...
}
// Other repository methods...
}

public class GenericDb1Repository<T, TContext>
where T : class
where TContext : DbContext, new()
{
internal TContext context;
internal DbSet<T> dbSet;
public GenericRepository(TContext context) {
this.context = context;
this.dbSet = context.set<T>();
}
public virtual T GetByID (int id) {
// code to return a T object by id...
}
// Other repository methods...
}**

Related

What is better way to update data in EF Core

What is the best way to update data in EF core in asp.net core application?
I can do it like this
public class Repository<T> : IRepository<T> where T : BaseEntity
{
private DbContext context;
private DbSet<T> entities;
public Repository(DbContext context)
{
this.context = context;
this.entities = context.Set<T>();
}
public void Update(T entity)
{
T exist = this.entities.Find(entity.Id);
this.context.Entry(exist).CurrentValues.SetValues(entity);
this.context.SaveChanges();
}
}
Or i can use the Update() method of DbSet. But to use it I need to set QueryTrackingBehavior to "no-tracking" firstly, something like this:
public class Repository<T> : IRepository<T> where T : BaseEntity
{
private DbContext context;
private DbSet<T> entities;
public Repository(DbContext context)
{
this.context = context;
this.context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
this.entities = context.Set<T>();
}
public void Update(T entity)
{
this.entities.Update(entity);
this.context.SaveChanges();
}
}
Is it a good idea? What option is better and why?
According to EF Core documentaion
SetValues will only mark as modified the properties that have different values to those in the tracked entity. This means that when the update is sent, only those columns that have actually changed will be updated. (And if nothing has changed, then no update will be sent at all.)
So I think your first approach (this.context.Entry(exist).CurrentValues.SetValues(entity);)
should be the best for updating entity!

Which lifetime-manager do I register my DbContext into Unity container when writing a WPF application?

I am writing a new C# application on the top of Prism 6.3 framework using the well-known MVVM design pattern. I am using Unity IoC container to help me manage my dependencies.
I am using Entity Framework Core to interact with the database. However, I don't want to tightly couple my application to Entity Framework Core, so I implemented Repository and UnitOfWork patterns to make it easy for me to swap out the Entity Framework Core implementation if needed.
My repository implementation provides a method called Save() which calls EF Core's SaveChanges() method. The repositories are injected into my business-service so that my business-service expose one method to do a single task. For example, if I want to create a new order, I would call the Create(orderViewModel) method which internally calls the Add() and the Save() method on the OrderRepository.
Additionally, the UnitOfWork provides Save(), BeginTransaction(), Commit() and Rollback() methods which allow me control the transaction behavior. In another words it will give me the flexibility to either commit or rollback the SQL transaction when needed.
To explain my use case better, here is an example of how I would add new order to my database directly using the business-service without transaction or unit-of-work.
OrdersService.Create(orderViewModel); // this will call the `Add` and the `Save()` methods on the OrderRepository;
Here is another example which demonstrate how I would add a new order and order-items to my database using the business-services while using unit-of-work to start transaction and control the transaction.
using(var transaction = UnitOfWork.BeginTransaction())
{
try
{
var order = OrdersService.Create(orderViewModel);
OrdersService.CreateRange(order.Id, orderItemsViewModel);
transaction.Commit();
}
catch(Exception e)
{
Log.Add(e);
transaction.RollBack();
}
}
In the second example above, even-though the OrdersService.Save and OrdersService.SaveRange each call the SaveChanges() method the data are not committed to the database since I am wrapping them with a transaction.
Question: what LifeTimeManager should I register the DbContext, IUnitOfWork and each of my repositories with?
In a web environment, I would register everything using PerRequestLifetimeManager then during the request I am reusing the same DbContext and everything works fine and the DbContext is disposed at the end of the http request. But not sure how to register everything in a WPF application where I can still use transaction to control everything while allowing the repository to call the SaveChanges()
If needed here is my EntityRepository implementation
public class EntityRepository<TEntity, TKeyType> : IRepository<TEntity, TKeyType>
where TEntity : class
where TKeyType : struct
{
protected readonly DbContext Context;
protected readonly DbSet<TEntity> DbSet;
public EntityRepository(DbContext context)
{
Context = context;
DbSet = context.Set<TEntity>();
}
public TEntity Get(TKeyType id)
{
return DbSet.Find(id);
}
public IEnumerable<TEntity> GetAll()
{
return DbSet.ToList();
}
public bool Any(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.Any(predicate);
}
public IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.Where(predicate);
}
public TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.SingleOrDefault(predicate);
}
public virtual TEntity Add(TEntity entity)
{
var record = Context.Add(entity);
record.State = EntityState.Added;
return entity;
}
public virtual IEnumerable<TEntity> AddRange(IEnumerable<TEntity> entities)
{
Context.AddRange(entities);
return entities;
}
public void Remove(TEntity entity)
{
Context.Remove(entity).State = EntityState.Deleted;
}
public void RemoveRange(IEnumerable<TEntity> entities)
{
Context.RemoveRange(entities);
}
public void Update(TEntity entity)
{
DbSet.Attach(entity);
var record = Context.Entry(entity);
record.State = EntityState.Modified;
}
public IQueryable<TEntity> Query()
{
return DbSet;
}
public void Save()
{
Context.SaveChanges();
}
}
And here is my unit of work implementation
public sealed class UnitOfWork : IUnitOfWork
{
private bool IsDisposed = false;
private readonly DbContext Context;
public IOrderRepository Orders { get; private set; }
public IOrderItemRepository OrderItems { get; private set; }
public UnitOfWork(DbContext context)
{
Context = context;
Orders = new OrderRepository(context);
OrderItems = new OrderItemRepository(context);
}
public int Save()
{
Context.SaveChanges();
return 0;
}
public void Dispose()
{
Dispose(true);
}
public IDatabaseTransaction BeginTransaction()
{
return new EntityDatabaseTransaction(Context);
}
private void Dispose(bool disposing)
{
if (IsDisposed)
{
return;
}
if (disposing)
{
Context.Dispose();
}
IsDisposed = true;
}
}
Transient (an instance per view) lifetime would be the way to go if your DI doesn't support scoping, but then you would need to abstract away your DbContext being passed through into the repo's and unitOfWork, otherwise new instances of the DbContext will be passed in there. On construction of the page, a new instance is created, and on moving away from that view, that DBContext should be disposed of. UnitOfWork would follow the same path as you wouldn't want a UnitOfWork spanning multiple instances of a DBContext.
See http://blogs.microsoft.co.il/gilf/2010/02/07/entity-framework-context-lifetime-best-practices/. Otherwise, if your DI has the concept of container hierarchies, and you're able to create a container scope per view, then a singleton would work in this instance and you wouldn't need any abstractions mentioned above and would be quite a bit easier to work with.

Where to put DSet DataAccess logic using Entity Framework?

I'm using CodeFirst EF6 and I'd like to place all related "queries" into a single class.
Let's say I have a
DbSet<Car> Cars;
in my DbContext.
I tried to create a new class with my concrete DbSet as base class:
public class CarRepository : DbSet<Car>
in which I'd locate all car related operations.
When I replace DbSet with CarRepository in my DbContext class it won't get filled.
I then tried to derive from IDbSet but I'm not sure how to implement all needed methods.
Is there another way to achieve this goal without using an extension class?
You can simply create your own single class(your repository) and put your methods like this.
public class Repository<TEntity> where TEntity : class
{
private DbContext context;
private DbSet<TEntity> dbSet;
public Repository(DbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
}

Referencing Entity Framework in MVVM in layered architecture

My app is layered in 4 layers:
Core: where I put some general and interface classes.
Model: where my code-first classes, and other related to domain, such as entity configurations and repositories etc.
Vm: where the view models live. Referencing Model.
Desktop: where the desktop app lives. Referencing Vm.
I have installed Entity Framework into Model, ViewModel and Desktop.
My question is: is it enough to install it into Model only? Why to repeat again?
[Edit]
Here is my implementation of Repository and UnitOfWrok (
IRepository and Repository will be on Core):
public interface IRepository<TEntity> where TEntity : class
{
TEntity Get(int id);
IEnumerable<TEntity> GetAll();
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate);
void Add(TEntity entity);
void AddRange(IEnumerable<TEntity> entities);
void Remove(TEntity entity);
void RemoveRange(IEnumerable<TEntity> entities);
}
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected readonly DbContext Context;
public Repository(DbContext context)
{
Context = context;
}
public TEntity Get(int id)
{
return Context.Set<TEntity>().Find(id);
}
and so on...
}
Now, the new next interfaces and classed will be on Model
public interface ICountryRepository : IRepository<Country> {}
public class CountryRepository : Repository<Country>, ICountryRepository
{
public CountryRepository(CmsDbContext cmsDbContext)
: base(cmsDbContext) {}
}
interface IUnitOfWork : IDisposable
{
ICountryRepository CountryRepository { get; }
}
public class UnitOfWork : IUnitOfWork
{
private readonly CmsDbContext _context;
public UnitOfWork(CmsDbContext context)
{
_context = context;
CountryRepository = new CountryRepository(_context);
}
public ICountryRepository CountryRepository { get; private set; }
public int Commit()
{
return _context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
Now, in my ViewModel
private UnitOfWork Currentunitofwork;
Currentunitofwork = new UnitOfWork(new CmsDbContext());
I followed a description of a tutor in udemy.
Is this separation correct?
Move all repository (Entity framework) methods behind interfaces in the Core and reference those interfaces in the ViewModel project.
Core.dll
public class SomeModel {}
public interface ISomeModelRepositoryService
{
SomeModel GetById(int id);
void Save(SomeModel model);
}
Model.dll - this project implements Core's interfaces and contains only database methods (Entity framework in your case)
public class SomeModelRepositoryService : ISomeModelRepositoryService
{
public SomeModel GetById(int id)
{
//Entity framework code
}
public void Save(SomeModel model)
{
//Entity framework code
}
}
ViewModel.dll
public class SomeModelViewModel
{
private ISomeModelRepositoryService _RepositoryService;
public SomeModel Model { get; set; }
public SomeModelViewModel(ISomeModelRepositoryService repositoryService)
{
_RepositoryService = repositoryService;
}
public void Save()
{
_RepositoryService.Save(this.Model);
}
}
Create repository implementation instances in top startUp project(Main method for example) and put it to ViewModel as parameters:
ISomeModelRepositoryService repositoryService = new SomeModelRepositoryService();
SomeModelViewModel viewmodel = new SomeModelViewModel(repositoryService);
With this approach only "Model.dll" need to have references to Entity Framework

DBContext SaveChanges method in UnitOfWork or in Repository? Which is better?

I'm trying to use Unit Of Work pattern for the first time in MVC application that already follows a Repository Pattern with Entity Framework DbContext.
My question is regarding the best place/practice on calling the Savechanges() method.
I see 2 approaches possible:
Call it in Unit Of Work class(Approach mentioned in Asp.Net site)
Call in Repository class
For the first approach, we have to call SaveChanges() on UnitOfWork instance injected in Controller.
For the second approach, SaveChanges() will be encapsulated in Repository and all Controller needs to do is invoke method in Repository(provided by UnitOfWork) and SaveChanges() will be called inside Repository.
Approach 1:
public class PostsController : Controller
{
private readonly IRepository<Post> _postRepository;
private readonly IRepository<Category> _categoryRepository;
private readonly IUnitOfWork _uow;
public PostsController(IUnitOfWork uow)
{
if (uow == null)
throw new ArgumentNullException(nameof(uow));
_uow = uow;
_postRepository = uow.Repository<Post>();
_categoryRepository = uow.Repository<Category>();
}
[HttpPost]
public ActionResult Create(Post post)
{
if (ModelState.IsValid)
{
_postRepository.Add(post);
_uow.SaveChanges();
}
return View(post);
}
}
public class UnitOfWork : IUnitOfWork
{
private CodingSoldierDbContext _dbContext;
private Dictionary<Type, object> _repositories = new Dictionary<Type, object>();
public UnitOfWork(DbContext dbContext)
{
if (dbContext == null)
throw new ArgumentNullException(nameof(dbContext));
_dbContext = dbContext as CodingSoldierDbContext;
}
public IRepository<T> Repository<T>() where T : class
{
if (_repositories.Keys.Contains(typeof(T)))
{
return _repositories[typeof(T)] as IRepository<T>;
}
IRepository<T> repository = new Repository<T>(_dbContext);
_repositories.Add(typeof(T), repository);
return repository;
}
public void SaveChanges()
{
_dbContext.SaveChanges();
}
}
public class Repository<T> : IRepository<T> where T : class
{
CodingSoldierDbContext _dbContext;
public Repository(DbContext dbContext)
{
if (dbContext == null)
throw new ArgumentNullException(nameof(dbContext));
_dbContext = dbContext as CodingSoldierDbContext;
}
public void Add(T item)
{
_dbContext.Set<T>().Add(item);
//_dbContext.SaveChanges();
}
}
Approach 2:
Not adding code so that question remains short.
In Approach 1, in Create method in Controller, remove the line:
_uow.SaveChanges();
Remove "SaveChanges" method definition from UnitOfWork.
Uncomment commented line in Repository Class:
_dbContext.SaveChanges()
I feel 2nd approach better than 1st approach in the sense code in controller is cleaner and SaveChanges is responsibility of the same class(Repository) who directly interact with DbContext.
Anyone, please let me know if you have any reason we should be following the 1st approach ?
I prefer to implement the SaveChanges on the UnitOfWork context because if you edit several entities from several repositories, you don't want to execute the save changes on each repository.
Example:
var unitOfWork = UnitOfWorkFactory.Create();
var categoryRepo = unitOfWork.GetRepository<Category>();
var postRepo= unitOfWork.GetRepository<Post>();
var cat = new Category("name");
categoryRepo.Add(cat);
var post = new Post("Title", "Message");
post.Category = cat;
postRepo.Add(post );
unitOfWork.SaveChanges();
It is easier to save the complete context (in one transition).
Both. In the UOW you need save changes to the context used by compound repositories. You need also savechanges method in the repositories like
public void SaveChanges()
{
context.SaveChanges();
}
For repository that is used independently

Categories

Resources