After read some articles about DI, Repository Pattern,... I have created a project with Asp.Net MVC. Below are some classes. It worked, but I'm wondering what I did are standard? Is that correct pattern? If no, how can I adjust to make it better?
Thank you in advance.
IGenericRepository interface:
public interface IGenericRepository<TEntity>: IDisposable where TEntity : class
{
IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "");
bool Contains(Expression<Func<TEntity, bool>> predicate);
TEntity GetById(params object[] keys);
TEntity Find(Expression<Func<TEntity, bool>> predicate);
TEntity Insert(TEntity t);
void Delete(TEntity t);
int Delete(Expression<Func<TEntity, bool>> predicate);
int Update(TEntity t);
int Count { get; }
}
GenericRepository class: (I will implement the functions later)
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity:class
{
internal GMSDbContext db;
internal DbSet<TEntity> dbSet;
public GenericRepository(GMSDbContext dbContext)
{
db = dbContext;
dbSet = db.Set<TEntity>();
}
public int Count
{
get
{
throw new NotImplementedException();
}
}
public bool Contains(Expression<Func<TEntity, bool>> predicate)
{
throw new NotImplementedException();
}
public int Delete(Expression<Func<TEntity, bool>> predicate)
{
throw new NotImplementedException();
}
public void Delete(TEntity t)
{
throw new NotImplementedException();
}
public TEntity Find(Expression<Func<TEntity, bool>> predicate)
{
throw new NotImplementedException();
}
public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
throw new NotImplementedException();
}
public TEntity GetById(params object[] keys)
{
throw new NotImplementedException();
}
public TEntity Insert(TEntity t)
{
throw new NotImplementedException();
}
public int Update(TEntity t)
{
throw new NotImplementedException();
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
db.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
IAccountRepository interface:
public interface IAccountRepository : IGenericRepository<Account>
{
}
AccountRepository class:
public class AccountRepository: GenericRepository<Account>,IAccountRepository
{
public AccountRepository(GMSDbContext db) : base(db) { }
}
IUnitOfWork interface:
public interface IUnitOfWork: IDisposable
{
void SaveChanges();
IAccountRepository AccountRepository { get; }
}
UnitOfWork class:
public class UnitOfWork : IUnitOfWork
{
private GMSDbContext db;
private IAccountRepository accountRepo;
public UnitOfWork()
{
db = new GMSDbContext();
}
public IAccountRepository AccountRepository
{
get
{
if (accountRepo != null) return accountRepo;
else return new AccountRepository(db);
}
}
public void SaveChanges()
{
db.SaveChanges();
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
db.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
IAccountService interface:
public interface IAccountService
{
int CheckLogin(string username, string password);
Account GetAccountByUsername(string username);
}
AccountService class:
public class AccountService : IAccountService, IDisposable
{
private IUnitOfWork unitOfWork;
public AccountService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
#region Serivce Methods
public int CheckLogin(string username, string password)
{
var entity = unitOfWork.AccountRepository.
Find(o => o.Username.Equals(username, StringComparison.OrdinalIgnoreCase)
&& o.Password.Equals(password, StringComparison.OrdinalIgnoreCase));
if (entity == null) return -1;
else {
if (entity.IsEnabled) return 0;
else return -2;
}
}
public Account GetAccountByUsername(string username)
{
throw new NotImplementedException();
}
#endregion
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
unitOfWork.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
AccountController class:
public class AccountController : Controller
{
private IAccountService accountService;
public AccountController(IAccountService accountService)
{
this.accountService = accountService;
}
// GET: Admin/Account
public ActionResult Index()
{
return View();
}
}
I use Simple Injector for IOC container:
public static class SimpleInjectorInitializer
{
/// <summary>Initialize the container and register it as MVC3 Dependency Resolver.</summary>
public static void Initialize()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
private static void InitializeContainer(Container container)
{
// For instance:
container.Register<IAccountService, AccountService>(Lifestyle.Scoped);
container.Register<IUnitOfWork, UnitOfWork>(Lifestyle.Scoped);
}
}
Repositories and UnitOfWork on top of EntityFramework context is not a good idea .
When you're using EntityFramework and you instantiate your DbContext – you're creating a new UnitOfWork.
There is no point in creating IGenericRepository<TEntity>
and then implementing it for each entity. As you are just wrapping DbContext and create unneeded code. If you don't want to create/inject an instance of DbContext into your controller (eg for Unit testing). You may create an IGMSDbContext
interface and its implementation like:
public interface IGMSDbContext
{
DbSet<Account> Accounts { get; set; }
int SaveChanges();
}
public class GMSDbContext: DbContext, IGMSDbContext
{
public DbSet<Account> Accounts { get; set; }
public GMSDbContext(string connection) : base(connection)
{
}
public GMSDbContext() : base("your connection string name")
{
}
}
Then just inject IGMSDbContext
into your service:
private IGMSDbContext dbContext;
public AccountService(IGMSDbContext dbContext)
{
this.dbContext = dbContext;
}
In this way you can use context in your code this.dbContext.Accounts.Where....
Above implementation has a number of benefits:
IGenericRepository<T>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.