I know that this question seems to be already made here, but I have specific doubts, mainly in database-first usage and lack of code-example in replied questions.
I have these layers: Core, Data and UI (asp.net mvc).
I have these tables in MSSQL: Person and Contact.
Question 1: In data layer, EDMX generates Person and Data POCO. Where I write methods like SearchPersonByCity() ? Do I need to create another Person class in the same data layer, just for writting data CRUD? How I make this? Please make an example (classes, namespaces, etc.. not necessary the whole actual code)
Question 2: How do I transpose these data between data-layer and core (domain models)? Where do I need to create the same SearchPersonByCity() in core (domain) class? Maybe create another Person class in core-layer just for these data-acess methods?
Please give me some code example, and how big companies do in real life, because it seems to be so dumb and a lot of code to mantain and problaby I'm getting something wrong.
I'm not lazy, and I read hundreds pages of Entity Framework books, questions here, and I can't figure out how to do this in code.
In my opinion I would use the repository pattern in your case, so first you have a IRepository class defined:
public interface IRepository<T> where T :
{
void Add(T entity);
void Update(T entity);
void Delete(T entity);
void Delete(Expression<Func<T, bool>> where);
T GetById(long id);
T GetById(string id);
T Get(Expression<Func<T, bool>> where);
}
And an abstract base RepositoryBase class:
public abstract class RepositoryBase<T> where T : class
{
private PersonDBEntities dataContext;
private readonly IDbSet<T> dbset;
protected RepositoryBase(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
dbset = DataContext.Set<T>();
}
protected IDatabaseFactory DatabaseFactory
{
get;
private set;
}
protected PersonDBEntities DataContext
{
get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
}
public virtual void Add(T entity)
{
dbset.Add(entity);
}
public virtual void Update(T entity)
{
dbset.Attach(entity);
dataContext.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(T entity)
{
dbset.Remove(entity);
}
public virtual void Delete(Expression<Func<T, bool>> where)
{
IEnumerable<T> objects = dbset.Where<T>(where).AsEnumerable();
foreach (T obj in objects)
dbset.Remove(obj);
}
public virtual T GetById(long id)
{
return dbset.Find(id);
}
public virtual T GetById(string id)
{
return dbset.Find(id);
}
public virtual IEnumerable<T> GetAll()
{
return dbset.ToList();
}
//You can return IQueryable if you want to build your expression true later on...
public virtual IEnumerable<T> Get(Expression<Func<T, bool>> where)
{
return dbset.Where(where).ToList();
}
}
And your PersonRepository class:
public class PersonRepository: RepositoryBase<Person>, IPersonRepository
{
public PersonRepository(IDatabaseFactory databaseFactory)
: base(databaseFactory)
{
}
}
public interface IPersonRepository : IRepository<Person> // Person will be your POCO class
{
}
Next step is on your service layer, you will define and implement that actual SearchPersonByCity() method:
public class PersonService : IPersonService
{
private readonly IPersonRepository personRepository;
private readonly IUnitOfWork unitOfWork;
public PersonService(IPersonRepository personRepository, IUnitOfWork unitOfWork)
{
this.personRepository = personRepository;
this.unitOfWork = unitOfWork;
}
public IEnumerable<Person> SearchPersonByCity(string city)
{
var persons = personRepository.Get(p => p.City == city);
return persons;
}
}
Related
I've an already existing SQL database that has table Car for example that looks like this
public class Car
{
public string Brand { get; set; }
public string AvailableColorsCommaSperated { get; set; }
}
Now I'm working on migrating to MongoDb so that the data could look like that
public class Car
{
public string Brand { get; set; }
public List<string> Colors { get; set; }
}
But I've to maintain the SQL database at the same time as it will remain used for sometime even after migration.
Now in my DAL layer I had a Master interface and class that looks like Repository pattern which the interface was like that
public interface ICarDAL
{
List<Car> GetAllCars();
}
public class CarDAL : ICarDAL
{
private readonly ICarSQL carSQL;
public CarDAL(ICarSQL carSQL)
{
this.carSQL = carSQL;
}
public List<Car> GetAllCars()
{
return carSQL.GetAllCars();
}
}
While to implement that using the SQLContext another interface and class with implementation exists as so
public interface ICarSQL : ICarDAL
{
new List<Car> GetAllCars();
}
public class CarSQL : ICarSQL
{
private readonly DbContext dbContext;
public CarSQL(DbContext dbContext)
{
this.dbContext = dbContext;
}
public List<Car> GetAllCars()
{
// Get Cars..
}
}
I could have no problem of adding a seperate layer for the Mongo to inherit from the ICarDAL and implement the functions on its own, but the problem is that I will have different Car Model for each one of them (the Car is just an example)
How can I abstract the DAL layer so that I can make the CRUD operations with different Models to different Databases? and am I going to need different context or use the same one with a factory to distinguish between different databases classes?
you can make your interface more generic
public interface IGenericRepository<T> where T : class
{
IEnumerable<T> GetAll();
T GetById(object id);
void Insert(T obj);
void Update(T obj);
void Delete(object id);
void Save();
}
so each dal layer will implement it's own version
you can even use a different type for an ID
for example:
public interface IGenericRepository<T,K> where T : class
{
IEnumerable<T> GetAll();
T GetById(K id);
void Insert(T obj);
void Update(T obj);
void Delete(K id);
void Save();
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm learning about Repository Pattern and I found many code examples but all are almost the same so I have doubts to that respect, for example this design:
public interface IRepository<T>
{
void Add(T entity);
void Update(T entity);
void Delete(T entity);
IList<T> GetAll();
}
public interface IPostRepository
{
int GetComentCount();
}
public class EFRepository<T>: IRepository<T>
{
public void Add(T entity){ /*implementation...*/ }
public void Update(T entity){ /*implementation...*/ }
public void Delete(T entity){ /*implementation...*/ }
public IList<T> GetAll(){ /*implementation...*/ }
}
public class PostRepository: EFRepository<Post>, IPostRepository
{
public int GetComentCount(){ /*implementation...*/ }
}
public class UnitOfWork: IUnitOfWork, IDisposable
{
IPostRepository PostRepository {get;}
}
I can do this:
IUnitOfWork UoW = new UnitOfWork();
int nComments = UoW.PostRepository.GetComentCount();
but not this: (obviously)
var collection = UoW.PostRepository.GetAll();
What I have to do? Must I create another property in UoW and return an IRepository?
Must I create an interface for every Repository with no CRUD operations (for example IPostRepository)? Must a concrete repository inherit from EFRepository class and the interface at a time (for example: class PostRepository: EFRepository, IPostRepository{})?
What do you think?
PD: Pardon my poor english.
If you change IPostRepository to inherit from IRepository, you are simply extending the interface surface, so you don't need to redefine all the methods.
For example, with this change:
public interface IRepository<T>
{
void Add(T entity);
void Update(T entity);
void Delete(T entity);
IList<T> GetAll();
}
public interface IPostRepository : IRepository<int>
{
int GetComentCount();
}
public class EFRepository<T> : IRepository<T>
{
public void Add(T entity) { Console.WriteLine("Works"); }
public void Update(T entity) { /*implementation...*/ }
public void Delete(T entity) { /*implementation...*/ }
public IList<T> GetAll() { return null; }
}
public class PostRepository : EFRepository<int>, IPostRepository
{
public int GetComentCount() { return 0; }
}
public interface IUnitOfWork
{
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
public IPostRepository PostRepository { get { return new PostRepository(); } }
public void Dispose()
{
throw new NotImplementedException();
}
}
The following code will print Works:
UnitOfWork t = new UnitOfWork();
t.PostRepository.Add(1);
Basically, your PostRepository does not need to reimplement the Add/Update/Delete methods as that interface contract is already present in the base class EFRepository and will be used. IPostRepository will force you to only provide the extended interface contract.
As for best practices, I don't think there is a single good solution. I try to go with the inherit approach, but I have seen good production code that has ReadOnly/Add/AddUpdate/etc. repository interfaces for composition.
P.S. I changed Post class with int in the example to avoid defining a whole new class.
I have written 3 repositories with the same format. How do I create a generic repository?
public class MyRepository : MyDataRepositoryBase<ASD>
{
protected override ASD AddEntity(MyDataContext entityContext, ASD entity)
{
return entityContext.ASDSet.Add(entity);
}
protected override IEnumerable<ASD> GetEntities(MyDataContext entityContext)
{
return from e in entityContext.ASDSet
select e;
}
}
This is where I am so far...
public class ComponentsRepository<T, U>:MyDataRepositoryBase<T>
where T : class,new()
where U : DbSet<U>, new()
{
protected override T AddEntity(MyDataContext entityContext, T entity)
{
return entityContext.U.Add(entity);
}
}
I am basically trying to find a way to call the DbSet "entityContext.ASDSet" without knowing what it is.
Any ideas or should I just let it go...
Entity Framework has a Set Method so you could do this
return entityContext.Set<T>().Add(entity);
But it won't check that you are passing in a class that isn't mapped. So it's use at your own risk, will throw an exception if it's not mapped. We have a base class that all our entity inherit from so we put a constraint on that, but even that there is no guarantee that a class is mapped in entity framework.
For what it's worth the generic repository is considered an anti-pattern. This is the implementation I used to use:
public class Repository<T> : IRepository<T> where T : class
{
private readonly IDbContext _context;
private readonly IDbSet<T> _dbSet;
public Repository(IDbContext context) {
_context = context;
_dbSet = context.Set<T>();
}
public void Add(T entity) {
_dbSet.Add(entity);
}
public void Update(T entity) {
_context.Entry(entity).State = EntityState.Modified;
}
...
}
My IDbContext:
public interface IDbContext
{
IDbSet<T> Set<T>() where T : class;
DbEntityEntry Entry<T>(T entity) where T : class;
int SaveChanges();
...
}
I used this with a UnitOfWork that I did my saving through and repository retrieval. That said, I really do find creating repositories around my entities a lot cleaner.
My application is getting larger and so far I have a single MyDbContext which has all the tables I need in my application. I wish (for the sake of overview) to split them up into multiple DbContext, like MainDbContext, EstateModuleDbContext, AnotherModuleDbContext and UserDbContext.
I am unsure how this is done probably as I am right now using dependecy injection (ninject) to place my DbContext on my UnitOfWork class like:
kernel.Bind(typeof(IUnitOfWork)).To(typeof(UnitOfWork<MyDbContext>));
Should I drop this approach with dependency injection and explicit set the DbContext I wish to use on my services like:
private readonly EstateService _estateService;
public HomeController()
{
IUnitOfWork uow = new UnitOfWork<MyDbContext>();
_estateService = new EstateService(uow);
}
Instead of:
private readonly EstateService _estateService;
public HomeController(IUnitOfWork uow)
{
_estateService = new EstateService(uow);
}
Or this there another better approach? Also as a side question, I dont like passing the uow to my service - is there another (better) approach?
Code
I have this IDbContext and MyDbContext:
public interface IDbContext
{
DbSet<T> Set<T>() where T : class;
DbEntityEntry<T> Entry<T>(T entity) where T : class;
int SaveChanges();
void Dispose();
}
public class MyDbContext : DbContext, IDbContext
{
public DbSet<Table1> Table1 { get; set; }
public DbSet<Table2> Table1 { get; set; }
public DbSet<Table3> Table1 { get; set; }
public DbSet<Table4> Table1 { get; set; }
public DbSet<Table5> Table1 { get; set; }
/* and so on */
static MyDbContext()
{
Database.SetInitializer<MyDbContext>(new CreateDatabaseIfNotExists<MyDbContext>());
}
public MyDbContext()
: base("MyDbContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
Then I have this IRepository and the implementation:
public interface IRepository<T> where T : class
{
IQueryable<T> GetAll();
void Add(T entity);
void Delete(T entity);
void DeleteAll(IEnumerable<T> entity);
void Update(T entity);
bool Any();
}
public class Repository<T> : IRepository<T> where T : class
{
private readonly IDbContext _context;
private readonly IDbSet<T> _dbset;
public Repository(IDbContext context)
{
_context = context;
_dbset = context.Set<T>();
}
public virtual IQueryable<T> GetAll()
{
return _dbset;
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
var entry = _context.Entry(entity);
entry.State = EntityState.Deleted;
_dbset.Remove(entity);
}
public virtual void DeleteAll(IEnumerable<T> entity)
{
foreach (var ent in entity)
{
var entry = _context.Entry(ent);
entry.State = EntityState.Deleted;
_dbset.Remove(ent);
}
}
public virtual void Update(T entity)
{
var entry = _context.Entry(entity);
_dbset.Attach(entity);
entry.State = EntityState.Modified;
}
public virtual bool Any()
{
return _dbset.Any();
}
}
And the IUnitOfWork and implemention which handles the work done with the DbContext
public interface IUnitOfWork : IDisposable
{
IRepository<TEntity> GetRepository<TEntity>() where TEntity : class;
void Save();
}
public class UnitOfWork<TContext> : IUnitOfWork where TContext : IDbContext, new()
{
private readonly IDbContext _ctx;
private readonly Dictionary<Type, object> _repositories;
private bool _disposed;
public UnitOfWork()
{
_ctx = new TContext();
_repositories = new Dictionary<Type, object>();
_disposed = false;
}
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
// Checks if the Dictionary Key contains the Model class
if (_repositories.Keys.Contains(typeof(TEntity)))
{
// Return the repository for that Model class
return _repositories[typeof(TEntity)] as IRepository<TEntity>;
}
// If the repository for that Model class doesn't exist, create it
var repository = new Repository<TEntity>(_ctx);
// Add it to the dictionary
_repositories.Add(typeof(TEntity), repository);
return repository;
}
public void Save()
{
_ctx.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (this._disposed) return;
if (disposing)
{
_ctx.Dispose();
}
this._disposed = true;
}
}
Don't split your modular data pieces into multiple DbContexts unless there are logical seams for doing so. Entities from DbContextA cannot have automatic navigation or collection properties with entities in DbContextB. If you split the context, your code would have to be responsible for manually enforcing constraints and loading related data between contexts.
For "sake of overview" (a.k.a. keeping your sanity), you can still organize your CLR code and database tables by module. For the POCO's, keep them in different folders under different namespaces. For tables, you can group by schema. (However you probably should also take security considerations into account when organizing by SQL schema. For example, if there are any db users that should have restricted access to certain tables, design the schemas according to those rules.) Then, you can do this when building the model:
ToTable("TableName", "SchemaName"); // put table under SchemaName, not dbo
Only go with a separate DbContext when its entities have no relationships with any entities in your first DbContext.
I also agree with Wiktor in that I don't like your interface & implementation design. I especially don't like public interface IRepository<T>. Also, why declare multiple public DbSet<TableN> TableN { get; set; } in your MyDbContext? Do me a favor, read this article, then read this one.
You can greatly simplify your code with an EF interface design like this:
interface IUnitOfWork
{
int SaveChanges();
}
interface IQueryEntities
{
IQueryable<T> Query<T>(); // implementation returns Set<T>().AsNoTracking()
IQueryable<T> EagerLoad<T>(IQueryable<T> queryable, Expression<Func<T, object>> expression); // implementation returns queryable.Include(expression)
}
interface ICommandEntities : IQueryEntities, IUnitOfWork
{
T Find<T>(params object[] keyValues);
IQueryable<T> FindMany<T>(); // implementation returns Set<T>() without .AsNoTracking()
void Create<T>(T entity); // implementation changes Entry(entity).State
void Update<T>(T entity); // implementation changes Entry(entity).State
void Delete<T>(T entity); // implementation changes Entry(entity).State
void Reload<T>(T entity); // implementation invokes Entry(entity).Reload
}
If you declare MyDbContext : ICommandEntities, you just have to set up a few methods to implement the interface (usually one-liners). You can then inject any of the 3 interfaces into your service implementations: usually ICommandEntities for operations that have side effects, and IQueryEntities for operations that don't. Any services (or service decorators) responsible only for saving state can take a dependency on IUnitOfWork. I disagree that Controllers should take a dependency on IUnitOfWork though. Using the above design, your services should save changes before returning to the Controller.
If having multiple separate DbContext classes in your app ever makes sense, you can do as Wiktor suggests and make the above interfaces generic. You can then dependency inject into services like so:
public SomeServiceClass(IQueryEntities<UserEntities> users,
ICommandEntities<EstateModuleEntities> estateModule) { ... }
public SomeControllerClass(SomeServiceClass service) { ... }
// Ninject will automatically constructor inject service instance into controller
// you don't need to pass arguments to the service constructor from controller
Creating wide per-aggregate (or even worse per-entity) repository interfaces can fight with EF, multiply boring plumbing code, and over-inject your constructors. Instead, give your services more flexibility. Methods like .Any() don't belong on the interface, you can just call extensions on the IQueryable<T> returned by Query<T> or FindMany<T> from within your service methods.
Your unit of work interface is not generic but the implementation is. The easiest way to clean up this would be to decide and follow the same convention.
For example, make your interface generic also. This way you could register three different interfaces (the same interface with three different generic parameters) to three different implementations:
container.Bind( typeof<IUnitOfWork<ContextOne>> ).To( typeof<UnitOfWork<ContextOne>> );
...
And yes, this is a good idea to inject your unit of works into controllers / services.
[Edited: The entities below are generated by Entity-Framework]
I am trying to implement a generic repository. Below are some interfaces that define specialize traits.
namespace AnimeVoter.DataLayer.Repositories
{
internal interface ICanCreate<TEntity>
{
void Create(TEntity entity);
}
internal interface ICanUpdate<TEntity>
{
bool Update(TEntity entity);
}
internal interface ICanDelete<TEntity>
{
bool Delete(TEntity entity);
}
internal interface ICanGetList<TEntity>
{
IEnumerable<TEntity> GetList();
}
internal interface ICanGetById<TEntity>
{
TEntity GetById(int id);
}
}
Now I also have an abstract class that combines the traits like below.
namespace AnimeVoter.DataLayer.Repositories
{
public abstract class CrudRepository<TEntity> :
ICanCreate<TEntity>,
ICanUpdate<TEntity>,
ICanDelete<TEntity>,
ICanGetList<TEntity>,
ICanGetById<TEntity>
{
public abstract void Create(TEntity entity);
public abstract bool Update(TEntity entity);
public abstract bool Delete(TEntity entity);
public abstract IEnumerable<TEntity> GetList();
public abstract TEntity GetById(int id);
}
}
Then I have somewhere like 10-15 concrete classes that uses the abstraction above. I will show only two. I will also limit the discussion to the common method Create().
Below is for the User table in the database:
namespace AnimeVoter.DataLayer.Repositories.Impl
{
public class UserRepository : CrudRepository<User>, IDisposable
{
DbEntities db = new DbEntities();
public override void Create(User entity)
{
db.Users.AddObject(entity);
}
...
And below is for the Title table in the database:
namespace AnimeVoter.DataLayer.Repositories.Impl
{
public class TitleRepository : CrudRepository<Title>, IDisposable
{
DbEntities db = new DbEntities();
public override void Create(Title entity)
{
db.Titles.AddObject(entity);
}
...
So there's the problem! When I am adding a new record to the User table I do db.Users.AddObject(entity). And when adding to the Title table I do db.Titles.AddObject(entity).
I am now wondering how I can refactor this using generics so I can just do something like db<"TableName">.AddObject(entity) or anything to that effect so I can have just one implementation for all the tables instead of having many implementations for each one of them?
The main thing you need to do is create an ObjectSet for the entity and then perform your actions against that ObjectSet instance. Here is a complete example on how to create a generic repository that handles all the CRUD actions.
public class TitleRepository : CrudRepository<Title>
{
public TitleRepository()
: base(new DbEntities())
{
}
}
public abstract class CrudRepository<TEntity> :
ICanCreate<TEntity>,
ICanUpdate<TEntity>,
ICanDelete<TEntity>,
ICanGetList<TEntity>,
ICanGetById<TEntity>
where TEntity : EntityObject
{
private readonly ObjectSet<TEntity> _objectSet;
private readonly string _primaryKey;
protected CrudRepository(ObjectContext context)
{
this._objectSet = context.CreateObjectSet<TEntity>();
this._primaryKey = this.GetPrimaryKeyPropertyName();
}
public void Create(TEntity entity)
{
this._objectSet.AddObject(entity);
this._objectSet.Context.SaveChanges();
}
public bool Update(TEntity entity)
{
if (entity.EntityState == EntityState.Detached)
{
this._objectSet.Attach(entity);
}
this._objectSet.Context.SaveChanges();
return true;
}
public bool Delete(TEntity entity)
{
this._objectSet.DeleteObject(entity);
this._objectSet.Context.SaveChanges();
return true;
}
public IEnumerable<TEntity> GetList()
{
return this._objectSet.ToList();
}
public TEntity GetById(int id)
{
return this._objectSet.Where(this.CreateGetByIdExpression(id)).FirstOrDefault();
}
// Build an Expression that can be used to query an Entity by Id.
private Expression<Func<TEntity, bool>> CreateGetByIdExpression(object id)
{
ParameterExpression e = Expression.Parameter(typeof(TEntity), "e");
PropertyInfo pi = typeof(TEntity).GetProperty(this._primaryKey);
MemberExpression m = Expression.MakeMemberAccess(e, pi);
ConstantExpression c = Expression.Constant(id, id.GetType());
BinaryExpression b = Expression.Equal(m, c);
Expression<Func<TEntity, bool>> lambda = Expression.Lambda<Func<TEntity, bool>>(b, e);
return lambda;
}
// Use the EF metadata to get the primary key property name.
private string GetPrimaryKeyPropertyName()
{
return this._objectSet.Context
.MetadataWorkspace
.GetEntityContainer(this._objectSet.Context.DefaultContainerName, DataSpace.CSpace)
.BaseEntitySets
.First(meta => meta.ElementType == this._objectSet.EntitySet.ElementType)
.ElementType.KeyMembers
.Select(k => k.Name)
.FirstOrDefault();
}
}
To accomplish this you have to define such mappings between entity type and db table. You can consider something like DbContractFactory and inject it in base CrudRepository<TEntity> class, so it will be able to retrieve Table reference/name in runtime based on current entity type TEntity like
dbContractFactory.GetDbContract<TEntity>()
In this way you can separate db-specifics from entities implementation itself by storing all relations in such factory/map.
EDIT: An example
interface IDbContract
{
string TableName { get; }
}
public sealed class DbContractFactory
{
private readonly IDictionary<Type, IDbContract> dbContractMap;
public void RegisterContract<TEntity>(IDbContract)
{
// store in dbContractMap
}
public IDbContract GetDbContract<TEntity>()
{
if (dbContractMap.Contains(typeof(TEntity))
{
// retrieve and return
}
}
}
Just replace the db.Title with CreateObjectSet
I do it something like this:
public class CrudRepository<TEntity> where TEntity : class
{
DbEntities db = new DbEntities();
public override void Create(TEntity entity)
{
db.CreateObjectSet<TEntity>().AddObject(entity);
}
}
EDIT:
Forgot the where...
I have found the answer here, http://geekswithblogs.net/seanfao/archive/2009/12/03/136680.aspx. This is very good because it eliminates having multiple repository objects for each table mapped by EF particularly for mundane operations like CRUD, which is exactly what I was looking for.