I am using a generic repository pattern Repository<TEntity> where repositories access the entities through a context. Then I have a service layer that accepts a context in the constructor. Now I can have multiple repositories in a service, accessing the entities through the same context. Pretty standard. This is perfect for tables/views that map to entities, but I cannot unit test data coming through stored procedures.
This is my current setup:
IDbContext:
public interface IDbContext : IDisposable
{
IDbSet<T> Set<T>() where T : class;
DbEntityEntry<T> Entry<T>(T entity) where T : class;
void SetModified(object entity);
int SaveChanges();
// Added to be able to execute stored procedures
System.Data.Entity.Database Database { get; }
}
Context:
public class AppDataContext : DbContext, IDbContext
{
public AppDataContext()
: base("Name=CONNECTIONSTRING")
{
base.Configuration.ProxyCreationEnabled = false;
}
public new IDbSet<T> Set<T>() where T : class
{
return base.Set<T>();
}
public void SetModified(object entity)
{
Entry(entity).State = EntityState.Modified;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new BookingMap());
}
// Added to be able to execute stored procedures
System.Data.Entity.Database Database { get { return base.Database; } }
}
Generic Repository:
public class Repository<T> : IRepository<T> where T : class
{
private readonly IDbContext context;
public Repository(IDbContext context)
{
this.context = context;
}
public IQueryable<T> GetAll()
{
return this.context.Set<T>().AsQueryable();
}
public void Add(T entity)
{
this.context.Set<T>().Add(entity);
}
public void Delete(T entity)
{
this.context.Set<T>().Remove(entity);
}
public void DeleteAll(IEnumerable<T> entities)
{
foreach (var e in entities.ToList())
{
this.context.Set<T>().Remove(e);
}
}
public void Update(T entity)
{
this.context.Set<T>().Attach(entity);
this.context.SetModified(entity);
}
public void SaveChanges()
{
this.context.SaveChanges();
}
public void Dispose()
{
if (this.context != null)
{
this.context.Dispose();
}
}
}
Service:
public class BookingService
{
IDbContext _context;
IRepository<Booking> _bookingRepository;
public BookingService(IDbContext context)
{
_context = context;
_bookingRepository = new Repository<Booking>(context);
}
public IEnumerable<Booking> GetAllBookingsForName(string name)
{
return (from b in _bookingRepository.GetAll()
where b.Name == name
select b);
}
}
Test:
[TestClass]
public class BookingServiceTest
{
[TestMethod]
public void Test_Get_All_Bookings_For_Name()
{
var mock = new Mock<IDbContext>();
mock.Setup(x => x.Set<Booking>())
.Returns(new FakeDbSet<Booking>
{
new Booking { Name = "Foo" },
new Booking { Name = "Bar" }
});
BookingService _bookingService = new BookingService(mock.Object);
var bookings = _bookingService.GetAllBookingsForName(name);
Assert.AreEqual(2, bookings.Count(), "Booking count is not correct");
}
}
This is perfect for tables/views that map to entities, but I cannot unit test data coming through stored procedures.
I looked up on the internet and found DbContext.Database property and I am able to execute stored procedures with the .SqlQuery() function and map them to an entity type.
This is what I added to the Repository<T> class:
public IEnumerable<T> SqlQuery(string storedProc, params object[] paramList)
{
return this.context.Database.SqlQuery<T>(storedProc, paramList);
}
And call the .SqlQuery() function in my service class:
public IEnumerable<Booking> GetAllBookings(string name)
{
return _bookingRepository.SqlQuery("EXEC GetAllBookings #name = {0}", name);
}
This works great (I am able to get some data), but my question is how can I mock and unit test this?
I just encountered a need to do this, and my googling led me to this question. I didn't like the answer from Sriram Sakthivel, I didn't want to have to introduce yet another abstraction when I already had one in place:
I already had an interface which I had extracted from my DbContext, and implemented in a test double.
I simply added int ExecuteSqlCommand(string sql, params object[] parameters) to my interface, and in the actual context I implemented it like this:
public int ExecuteSqlCommand(string sql, params object[] parameters)
{
return Database.ExecuteSqlCommand(sql, parameters);
}
Which obviously just delegates to the actual EF Database property to do the work.
And in my test double I implemented it like this:
public int ExecuteSqlCommand(string sql, params object[] parameters)
{
return 0;
}
Which doesn't really do anything, which is the point: You aren't unit testing the actual stored procedure, you just need a way to get it to return something useful.
I imagine at some point I 'might' need it to return something other than 0 in a unit test, at which point I'll probably introduce something like a Func<int> executeSqlCommandResultFactory to test double constructor so that I can control it, but at the moment YAGNI applies.
You can abstract away the Database property with some interface say IDatabase with SqlQuery method.
interface IDatabase
{
public IEnumerable<T> SqlQuery<T>(string sql, params Object[] parameters);
}
class DatabaseWrapper : IDatabase
{
private readonly Database database;
public DatabaseWrapper(Database database)
{
this.database = database;
}
public IEnumerable<T> SqlQuery<T>(string sql, params Object[] parameters)
{
return database.SqlQuery<T>(storedProc, paramList);
}
}
Modify your IDbContext interface to use IDatabase instead of concrete instance so that we can mock it.
public interface IDbContext : IDisposable
{
...
// Added to be able to execute stored procedures
IDatabase Database { get; }
}
and your implementation this way
public class AppDataContext : DbContext, IDbContext
{
private readonly IDatabase database;
public AppDataContext()
: base("Name=CONNECTIONSTRING")
{
base.Configuration.ProxyCreationEnabled = false;
this.database = new DatabaseWrapper(base.Database);
}
...
// Added to be able to execute stored procedures
IDatabase Database { get { return database; } }
}
At this point I believe you know how to mock the IDatabase to return the test data.
I realize this is an old question, but to anyone having a similar issue, here's my take.
Why not just use AutoFixture to create an object of the data you usually return from the stored procedure and mock your repository to return it?
public class FooBar
{
private Fixture fixture;
private Mock<BookingRepository> bookingRepository;
public FooBar()
{
fixture = new Fixture();
bookingRepository= new Mock<BookingRepository>();
}
public void TestInitialize()
{
var sprocObject = fixture.Create<DbObject>();
bookingRepository.Setup(x => x.GetAllBookings(It.IsAny<string>())).Returns(sprocObject);
}
// Unit tests
}
As Gert Arnold said, you should do integration tests if you want to test the actual stored procedure. If you're testing the service/repository logic you just need to return some data.
Related
I have a Web API web service that uses EF for database operations and Unity for dependency injection. I have multiple databases with different names but the same schema. There's one database per retail store. When the user logs in, depending on his privileges, he can select which store he wants to work with. This is a challenge using dependency injection because I have to change the database after a repository has been injected. I have something that works but am not sure if it's the best approach.
My specific questions are:
Is this a good approach for this problem? I've seen other questions that mention changing the connection string at run time, but I think I'd either have to have a connection string per store in my Web.Config or build the connection string dynamically somehow.
Do I need the Dispose logic in my factory? If I were injecting a repository directly I know I wouldn't need it. Since I'm generating the repo from an injected factory, can I trust Unity to dispose of the repo and close the db connections at some point? Should I use using statements around the generated repos instead?
Some questions I looked at while trying to solve this problem are this one, this one, and this one. However, none of them directly accomplish what I'm trying to do. Below is my current solution.
This is my repository and its interface. I've left out some of the methods for brevity:
IGenericRepository
public interface IGenericRepository<T> where T: class
{
IQueryable<T> Get();
void ChangeDatabase(string database);
void Update(T entityToUpdate);
void Save();
}
GenericRepository
public class GenericRepository<TDbSet, TDbContext> :
IGenericRepository<TDbSet> where TDbSet : class
where TDbContext : DbContext, new()
{
internal DbContext Context;
internal DbSet<TDbSet> DbSet;
public GenericRepository() : this(new TDbContext())
{
}
public GenericRepository(TDbContext context)
{
Context = context;
DbSet = Context.Set<TDbSet>();
}
public virtual IQueryable<TDbSet> Get()
{
return DbSet;
}
public void ChangeDatabase(string database)
{
var dbConnection = Context.Database.Connection;
if (database == null || dbConnection.Database == database)
return;
if (dbConnection.State == ConnectionState.Closed)
{
dbConnection.Open();
}
Context.Database.Connection.ChangeDatabase(database);
}
public virtual void Update(TDbSet entityToUpdate)
{
DbSet.Attach(entityToUpdate);
Context.Entry(entityToUpdate).State = EntityState.Modified;
}
public virtual void Save()
{
Context.SaveChanges();
}
}
In order to use dependency injection I'm injecting a repository factory to which I can pass a database name. The factory creates a repository with the connection string's default database, changes the database to the one specified, and returns the repository.
IRepositoryFactory
public interface IRepositoryFactory
{
IGenericRepository<TDbSet> GetRepository<TDbSet>(string dbName) where TDbSet : class;
}
StoreEntitiesFactory
public class StoreEntitiesFactory : IRepositoryFactory
{
private bool _disposed;
readonly StoreEntities _context;
public StoreEntitiesFactory()
{
_context = new StoreEntities();
}
public IGenericRepository<TDbSet> GetRepository<TDbSet>(string dbName) where TDbSet : class
{
var repo = new GenericRepository<TDbSet, StoreEntities>(_context);
repo.ChangeDatabase(dbName);
return repo;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_context.Dispose();
}
_disposed = true;
}
~StoreEntitiesFactory()
{
Dispose(false);
}
}
This is how I inject the repository factory in my WebApiConfig file:
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var container = new UnityContainer();
container.RegisterType<IRepositoryFactory, StoreEntitiesFactory>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
}
}
Finally, this is how I would use the factory in my controller:
StoreController
public class StoreController : ApiController
{
private readonly IRepositoryFactory _storeEntitiesRepoFactory;
public StoreController(IRepositoryFactory storeEntitiesRepoFactory)
{
_storeEntitiesRepoFactory = storeEntitiesRepoFactory;
}
[HttpGet]
public IHttpActionResult Get()
{
var dbName = getStoreDbName(storeNumberWeGotFromSomewhere);
try
{
var employeeRepo = _storeEntitiesRepoFactory.GetRepository<Employee>(dbName);
var inventoryRepo = _storeEntitiesRepoFactory.GetRepository<Inventory>(dbName);
var employees = employeeRepo.Get().ToList();
var inventory = inventoryRepo.Get().ToList();
}
catch (Exception ex)
{
return InternalServerError();
}
}
}
I think you probably want your IRepositoryFactory implementations to return the same repository for the same dbName. As it is written now, calling StoreEntitesFactory.GetRepository with two different dbName parameters will cause problems since it gives the same instance of StoreEntites to every repository.
To illustrate...
public class DemonstrationController
{
private readonly IRepositoryFactory _storeEntitiesRepoFactory;
public DemonstrationController(IRepositoryFactory storeEntitiesRepoFactory)
{
_storeEntitiesRepoFactory = storeEntitiesRepoFactory;
}
[HttpGet]
public IHttpActionResult Get()
{
var empRepo1 = _storeEntitiesRepoFactory.GetRepository("DB1");
var empRepo2 = _storeEntitiesRepoFactory.GetRepository("DB2");
// After the second line, empRepo1 is connected to "DB2" since both repositories are referencing the same
// instance of StoreEntities
}
}
If you changed StoreEntitiesFactory to return the same repository based on the given parameter, this would solve that problem.
public class StoreEntitiesFactory : IRepositoryFactory
{
private bool _disposed;
private Dictionary<string, StoreEntities> _contextLookup;
public StoreEntitiesFactory()
{
_contextLookup = new Dictionary<string, StoreEntities>();
}
public IGenericRepository<TDbSet> GetRepository<TDbSet>(string dbName) where TDbSet : class
{
if (!_contextLookup.TryGetValue(dbName, out StoreEntities context))
{
context = new StoreEntities();
// You would set up the database here instead of in the Repository, and you could eliminate
// the ChangeDatabase function.
_contextLookup.Add(dbName, context);
}
return new GenericRepository<TDbSet, StoreEntities>(context);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize();
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
foreach (var context in _contextLookup.Values)
{
context.Dispose();
}
}
_disposed = true;
}
}
}
As for the second question, you would need the dispose logic in the factory since it owns the instances of StoreEntities being created. No need to use using statements around the repositories it creates, just let Unity dispose of the factory.
I'd recommend you to use a design pattern called a Strategy Pattern to solve this problem.
This pattern allows you to change between two or more strategies on runtime.
Reference: https://en.wikipedia.org/wiki/Strategy_pattern
For the injection, I'd suggest you register two concrete classes on the Unity, one for each DB Connection and call the Resolve method for the one you need passing the string to instantiate the DB.
IUnityContainer container = new UnityContainer();
container.RegisterType<ICar, BMW>();
container.RegisterType<ICar, Audi>("LuxuryCar");
ICar bmw = container.Resolve<ICar>(); // returns the BMW object
ICar audi = container.Resolve<ICar>("LuxuryCar"); // returns the Audi object
Reference: https://www.tutorialsteacher.com/ioc/register-and-resolve-in-unity-container
About the Dispose, you can config all of these concrete classes to the DBs as Singletons, and let all the connections opened, but you will need to verify if this is possible to your application.
I want to create an abstraction layer between Entity Framework and the rest of my application. But I am having a few problems with Entity Framework.
Basically (I don't show you all the interface layers that I've created too), I've split my application into several projects like this :
Domain
Contains my domain object, an abstraction of my datastorage object
DAL
Creates a link between my datastorage and my business layer. Contains two types of elements :
Private ones : my EDMX, my database object, and some other generated objects providing me some useful methods like ToDomain/ToEntity
Public ones : my Data Access Object, providing CRUD methods
Business
Contains the logic of my application. Only knows about the public elements of the DAL and the Domain Layer.
Presentation
Presents the domain objects for the user. Only knows about the business layer.
As I said, I want to create an abstraction of my datastorage objects (in my case Database object, but I want a solution that works also for file or WCF storage for example) so that my business layer don't know anything about my DAL implementation.
Here is a glimpse of what I've done in my DAL :
public abstract class GenericDao<TEntity, TDomain, TDbContext> : IGenericDao<TDomain>
where TDbContext : DbContext, new()
where TEntity : class
where TDomain : class
{
protected TDbContext _context;
protected DbSet<TEntity> _dbSet;
public GenericDao(TDbContext dbContext)
{
this._context = dbContext;
this._dbSet = dbContext.Set<TEntity>();
}
public TDomain Create()
{
return this.ToDomain(this._dbSet.Create());
}
public IList<TDomain> GetAll()
{
return this._dbSet.ToList().Select(entity => this.ToDomain(entity)).ToList();
}
public void Update(TDomain domain)
{
var entity = this.ToEntity(domain);
var entry = this._context.Entry(entity);
entry.State = EntityState.Modified;
}
public void Remove(TDomain domain)
{
_dbSet.Remove(this.ToEntity(domain));
}
protected abstract TDomain ToDomain(TEntity entity);
protected abstract TEntity ToEntity(TDomain domain);
}
You will probably see what's wrong with my code by reading it: when I try to delete or update an entity, I am not manipulating an entity attached to Entity Framework. If I try to attach my entity to the dbContext, it fails because there is already an entity in the context with the same id.
I already thought about several solutions, but none of them please me.
Maybe am I doing something wrong in my approach? I am a little bit confused about the Repository and DAO pattern (I read anything and the very opposite about that difference on the internet).
You have two options:
initialize new dbcontext for each operation and dispose it when operation is ended:
public abstract class GenericDao<TEntity, TDomain, TDbContext> : IGenericDao<TDomain>
where TDbContext : DbContext, new()
where TEntity : class
where TDomain : class
{
protected Func<TDbContext> _contextFactory;
public GenericDao(Func<TDbContext> contextFactory)
{
_contextFactory = contextFactory;
}
public TDomain Create()
{
using(var context = _contextFactory())
{
return context.Set<TEntity>().Create();
}
}
public IList<TDomain> GetAll()
{
using(var context = _contextFactory())
{
return context.Set<TEntity>().ToList()
.Select(entity => this.ToDomain(entity)).ToList();
}
}
public void Update(TDomain domain)
{
using(var context = _contextFactory())
{
var entity = this.ToEntity(domain);
context.Attach(entity);
var entry = this._context.Entry(entity);
entry.State = EntityState.Modified;
context.SaveChanges();
}
}
public void Remove(TDomain domain)
{
using(var context = _contextFactory())
{
var entity = this.ToEntity(domain);
context.Attach(entity);
context.Set<TEntity>.Remove(entity);
context.SaveChanges();
}
}
protected abstract TDomain ToDomain(TEntity entity);
protected abstract TEntity ToEntity(TDomain domain);
}
or you can try to find entity in your instance of dbcontext using property Local of DbSet:
var contextEntity = context.Set<TEntity>().Local
.Where(c=>c.Id == entity.Id).FirstOrDefault();
You seem to be getting stuck coding to an implementation within your abstraction. If you injected an interface to your generic rather than a concrete type (like EF) then your GenericDao becomes much more flexible. You can inject whatever implementation you choose providing it implements the required interface. In your case, WCF, File, Whatever. For example;
protected IDbContext _context;
public GenericDao(IDbContext dbContext)
{
this._context = dbContext;
}
public void Remove(TDomain domain)
{
_context.Remove(this.ToEntity(domain));
}
//abstraction
public interface IDbContext
{
void Remove(Entity entity);
}
//EF Implementation
public MyEfClass : IDbContext
{
public void Remove(Entity entity)
{
//code to remove for EF example
context.Attach(entity);
context.State = EntityState.Modified;
context.Set<TEntity>.Remove(entity);
context.SaveChanges();
}
}
//WCF Implementation
public MyWCFClass : IDbContext
{
public void Remove(Entity entity)
{
//Wcf implementation here
}
}
//File example
public FileWriter : IDbContext
{
public void Remove(Entity entity)
{
LoadFile();
FindEntry(entity);
WriteFile(entity);
SaveFile();
}
public void LoadFile()
{
//use app settings for file directory
}
}
I'm writing a sync service between our Salesforce environment and our local environment. My use of the Salesforce API is purely on a batch level due to limitations on # of API requests per day, although I do have details on failures at the atomic level. However, I would like to save changes on a atomic level in my local environment as I don't want an entire transaction to fail if one entity fails.
I am using Entity Framework 6 with a Unit of Work and Repository pattern. Here is my relevant code (Implementation Details Below):
IUnitOfWork
public interface IUnitOfWork: IDisposable
{
IReadUpdateRepository<EntityType1> EntityType1Repository { get; }
ISyncRepository<EntityType2> EntityType2Repository { get; }
ISyncRepository<EntityType3> EntityType3Repository { get; }
...other repos
void SaveChanges();
}
Implementation of IUnitOfWork
public class UnitOfWork : IUnitOfWork
{
private bool _isDisposed;
private DbContext _context;
private ISyncRepository<Entity> _entityRepo;
...other private repos
public UnitOfWork(DbContext context)
{
_context = context;
}
public ISyncRepository<Entity> EntityRepository
{
get
{
if (_entityRepo == null)
_entityRepo = new GenericSyncRepository<Entity>(_context);
return _entityRepo ;
}
}
...other getters for other repos
public void SaveChanges()
{
//client classes handle all errors here
_context.SaveChanges();
}
private void dispose(bool isDisposing)
{
if (!_isDisposed)
{
if (isDisposing)
_context.Dispose();
}
_isDisposed = true;
}
public void Dispose()
{
dispose(true);
}
}
ISyncRepository
public interface ISyncRepository<T> where T : BaseEntity
{
void DeleteItems(IEnumerable<T> items);
void DeleteItemsById(IEnumerable<int> ids);
void DeleteItem(T item);
void InsertItems(IEnumerable<T> items);
void Insert(T item);
T GetItemById(int id);
List<T> GetItems(Expression<Func<T, bool>> predicate = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "");
}
Implementation of ISyncRepository
public class GenericSyncRepository<T> : ISyncRepository<T> where T : BaseEntity
{
private readonly DbContext _context;
private readonly DbSet<T> _set;
public GenericSyncRepository(DbContext context)
{
_context = context;
_set = _context.Set<T>();
}
public T GetItemById(int id)
{
var result = _set.Find(id);
return result;
}
public List<T> GetItems(Expression<Func<T, bool>> predicate = null, Func<IQueryable<T>,IOrderedQueryable<T>> orderBy = null ,string includeProperties = "")
{
IQueryable<T> query = _set.AsExpandable();
if (predicate != null)
{
query = query.Where(predicate);
}
if (!String.IsNullOrEmpty(includeProperties))
{
var splitProps = includeProperties.Split(',');
foreach (var prop in splitProps)
{
query = query.Include(prop);
}
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
return query.ToList();
}
public void DeleteItemsById(IEnumerable<int> ids)
{
var items = ids.Select(i => _set.Find(i));
DeleteItems(items);
}
public void DeleteItem(T item)
{
_set.Remove(item);
}
public void DeleteItems(IEnumerable<T> items)
{
_context.Set<T>().RemoveRange(items);
}
public void Insert(T item)
{
_set.Add(item);
}
public void InsertItems(IEnumerable<T> items)
{
_set.AddRange(items);
}
public List<T> GetViewItems(Expression<Func<T, bool>> predicate)
{
IQueryable<T> query = _set.AsExpandable();
return query.Where(predicate).ToList();
}
}
I am using this repository in services that relate to each object group involved in the sync, into which I inject the IUnitOfWork via the constructor:
private readonly IUnitOfWork _uow;
public EntityDataService(IUnitOfWork uow, ICamsSfDTOMapper mapper)
{
_uow = uow;
}
Then use the UoW to fetch repositories to performs queries:
var repo = _unitOfWork.PartyRepository;
var p = repo.GetItems(p => Ids.Contains(someValue));
And when inserts or updates are made, I can call SaveChanges:
_unitOfWork.SaveChanges();
This works great for data retrieval, however for data persistence, I run into a snag. On the local domain side, I want to iterate through objects one by one, saving changes or inserting and calling SaveChanges to persist. If an error occurs, I store it in a result object that I log at the end of each sync step and continue onto the next object to do work on.
However, as my app is currently structured, if a database exception occurs on SaveChanges, that validation error remains in the context until it is disposed. Since this context is injected into each repository in the UoW class, it sticks around for what I presume is the life of the entire sync process.
I am using Autofac for DI in a WindowsService hosted using TopShelf and I'm registering my UoW as such:
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().WithParameter("context", new EntityModel());
Here are my questions:
Should this question be posted to Code Review :)
I feel like I should invert my repository with UoW, with UoW being passed into each repository and my repositories being passed into each service (a service can make use of more than one repository)
Does it make sense to spin up a new DbContext for each SaveChanges and to have one DbContext (the one passed into UoW) as my read context and all other contexts new'ed up when SavingChanges?
Any help would be appreciated.
Doesn't bother me, I only use SO and don't intend to go anywhere else, and don't mind having questions like these on SO.
I would highly recommend that your service as for IRepository and your repository ask for IUoW. I even like to think of IRepository as more than just a barrier to EF. I normally only use a repository if either
I know for a fact in advance I will be implementing a non EF repository as well otherwise
I want to implement some actual logic which I want abstracted from my service and would not make it generic. E.g. I would make a UserProfileRepository, which would have methods such as SyncCurrentUserProfile rather than exposing Add/Insert/Update. Exposing Add/Insert/Update adds nothing to the equation if I don't plan to use a non EF based model.
It depends. If you don't use tracking, and have a lot of unrelated changes over time. Than yes, as each time you add/update something it will add it to the context, which causes future additions/modifications become slower. But if you are adding/modifying 10 things here and there, probably wouldn't worry about it not unless you need a fresh context each time.
I am actually writing a blog post about this. Will try to post a link later.
I am new in Moq and Unit Testing. I want to test my Repository and Unit of Work pattern with entity framework 5. But I don't understand where and how can I start.
My Repository Interface :
public interface ISmRepository<T>
{
void Add(T entity);
void Remove(T entity);
void Update(T entity);
IQueryable<T> SearchFor(Expression<Func<T, bool>> expression);
IQueryable<T> GetAll();
T GetById(Int64 id);
}
My Repository:
public class SmReporitory<T> : ISmRepository<T> where T : class, IEntity, new()
{
private readonly DbSet<T> _dbSet;
private readonly DbContext _dbContext;
public SmReporitory(DbContext dbContext)
{
_dbSet = dbContext.Set<T>();
_dbContext = dbContext;
}
public void Add(T entity)
{
_dbSet.Add(entity);
}
public void Remove(T entity)
{
_dbSet.Remove(entity);
}
public void Update(T entity)
{
_dbContext.Entry(entity).State = EntityState.Modified;
}
public IQueryable<T> SearchFor(Expression<Func<T, bool>> expression)
{
return _dbSet.Where(expression);
}
public IQueryable<T> GetAll()
{
return _dbSet;
}
public T GetById(long id)
{
return _dbSet.FirstOrDefault(x => x.Id == id);
}
}
My Unit Of Work Interface :
public interface ISmUnitOfWork : IDisposable
{
ISmRepository<BreakdownCause> BreakdownCasus { get; }
ISmRepository<BreakDownType> BreakDownTypes { get; }
ISmRepository<CompanyInformation> CompanyInformations { get; }
void Save();
}
My Unit Of Work Implementation :
public class SmUnitOfWork : ISmUnitOfWork
{
private readonly DbContext _dbContext;
private ISmRepository<BreakDownType> _breakDownTypes;
private ISmRepository<BreakdownCause> _breakdownCasus;
private ISmRepository<CompanyInformation> _companyInformations;
public SmUnitOfWork() : this(new SmDbContext())
{
}
public SmUnitOfWork(SmDbContext smDbContext)
{
_dbContext = smDbContext;
}
public ISmRepository<BreakdownCause> BreakdownCasus
{
get { return _breakdownCasus ?? (_breakdownCasus = new SmReporitory<BreakdownCause>(_dbContext)); }
}
public ISmRepository<BreakDownType> BreakDownTypes
{
get { return _breakDownTypes ?? (_breakDownTypes = new SmReporitory<BreakDownType>(_dbContext)); }
}
public ISmRepository<CompanyInformation> CompanyInformations
{
get { return _companyInformations ?? (_companyInformations = new SmReporitory<CompanyInformation>(_dbContext)); }
}
public void Save()
{
try
{
_dbContext.SaveChanges();
}
catch
{
throw;
}
}
public void Dispose()
{
if (_dbContext!=null)
{
_dbContext.Dispose();
}
}
Now I want to test ISmRepository interfaces method's.
I already referenced NUnit and Moq in a class library project. Now I need a starting point.
You really don't need to test your repositories as you have them written. The reason is that, as Mystere Man alluded, you're basically just wrapping the Entity Framework API. When working with EF and using either my own repositories or some DbContext I don't worry about testing these data access calls until integration testing time for the reasons already stated.
However, you can (and should) certainly mock your repositories and unit of work to test all of your other code that has dependencies on them. By testing your repositories you're really testing Entity Framework functionality and I'm sure that has been tested more thoroughly than you will. One thing you can do is not put business logic into your repositories that directly interact with EF but instead move that out to another layer that utilizes your repositories for data access.
The short answer is that you really can't. At least not fully. And the reason for that is that a moq'd EF context does not behave the same way as a real one does due to the inherent sql translation.
There is a lot of code that will pass a Moq'd context, but will blow up in a real one. As such, you cannot depend on Moqing of fakes with an EF context, and you have to use integration testing.
i try to write Generic Repository in EF 4. But my codes is not looking good. Because ExpressionEntities is not GENERIC.
I want to convert this codes:
public class DataRepository<T> : IRepository<T> where T : class
{
private ExpressionsEntities _context;
public DataRepository()
{
}
public DataRepository(ExpressionsEntities context)
{
_context = context;
}
}
to the following:
public class DataRepository<T> : IRepository<T> where T : class
{
private GetGenericEntityCONTEXT _context;
public DataRepository()
{
}
public DataRepository(GetGenericEntityCONTEXT context)
{
_context = context;
}
}
because ExpressionsEntities not global my entities : ExpressionsEntities1, ExpressionsEntities 2, ExpressionsEntities 3 etx... i need to write get take entity for example:
public class DataRepository<T> : IRepository<T> where T : class
{
private Entity _context;
public DataRepository()
{
}
public DataRepository(Entity context)
{
_context = context;
}
public class Main
{
main()
{
new DataRepository(ExpressionEntities)
}
}
}
Not 100% sure what your asking - from what i can understand, you wan't a way to dynamically create the entity set based on T.
Well that's easy enough:
public class DataRepository<T> : IRepository<T> where T : class
{
private ObjectContext _ctx;
public DataRepository<T>(ObjectContext ctx)
{
this._ctx = ctx;
}
public IObjectSet<T> CurrentEntitySet<T>()
{
get
{
var entityName = _plularizer.Pluralize(typeof(T).Name);
string entitySetName = string.Format("{0}.{1}", EntityContainerName, entityName);
return _ctx.CreateObjectSet<T>(entitySetName );
}
}
}
Then your specific Repository could do this (for example):
public class AppleRepository : DataRepository<Apple>
{
public AppleRepository(IObjectContext ctx) : base(ctx) {}
public ICollection<Apple> FindApples(Func<Apple,bool> predicate)
{
return CurrentEntitySet.Where(predicate).ToList();
}
}
And when your creating your repository, pass through the object context - preferably by DI:
var repository = new AppleRepository(new ExpressionEntities()); // should be DI'ed
Basically, we're making use of Pluralization (the same code used by Entity Framework to pluralize entity set names), and CreateObjectSet<T>.
So if you created a DataRepository<Apple>, that would translate to an entity set name of Apples (which should match the entity set on your model), and we create an entity set based on that.
The EntityContainerName property is what's on your EDMX - you should pass this through the ctor (via DI preferably).
Does that answer your question?
I prefer to get the entityName like this.
EntityContainer container = context.MetadataWorkspace.GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace);
EntitySetBase entitySet = container.BaseEntitySets.Where(item => item.ElementType.Name.Equals(typeof(T).Name)).FirstOrDefault();
var entityName = entitySet.Name
This deals with some cases if you have some classes pluralized, and some classes not.