Parameter less constructor error in ASP.Net Web API 2 - entity-framework-6

I'm trying to make RestFul API following a repository pattern. When I hit my API using postman then I see the parameter less constructor error. I can't find out actually what I wrong.
I'm using EntityFramework6 Database First Approach. I shared my all relevant code samples.
Here is my SSDBEntities.cs
public partial class SSDBEntities : DbContext
{
public SSDBEntities()
: base("name=SSDBEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Employee> Employees { get; set; }
public virtual DbSet<Product> Products { get; set; }
}
ProductController.cs
[RoutePrefix("api/ss/products")]
public class ProductController : ApiController
{
private readonly IProductService _productService;
public ProductController(IProductService productService)
{
_productService = productService;
}
[HttpGet]
[Route("get-products")]
public async Task<IHttpActionResult> GetProducts()
{
int total = 0;
List<ProductModel> model = _productService.getProducts();
return Ok(new ResponseMessage<List<ProductModel>>()
{
Result = model
});
}
}
IProductService.cs
public interface IProductService
{
List<ProductModel> getProducts();
}
ProductService.cs
public class ProductService : IProductService
{
private readonly ISSRepository<Product> _productRepository;
public ProductService(ISSRepository<Product> productRepository)
{
_productRepository = productRepository;
}
public List<ProductModel> getProducts()
{
List<Product> products = _productRepository.Where(x => x.IsActive == true).ToList();
List<ProductModel> models = ObjectConverter<Product, ProductModel>.ConvertList(products).ToList();
return models;
}
}
ISSRepository.cs
public interface ISSRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
DataTable ExecWithStoreProcedure(string query, IDictionary<string, object> values);
DataTable ExecWithSqlQuery(string query);
int ExecNoneQuery(string query);
}
IRepository.cs
public interface IRepository<T> where T : class
{
T FindOne(Expression<Func<T, bool>> predicate);
T FindOne(Expression<Func<T, bool>> predicate, List<string> includeProperties);
bool Exists(Expression<Func<T, bool>> predicate);
IQueryable<T> AsQueryable();
IQueryable<T> Where(Expression<Func<T, bool>> predicate);
int Count();
int Count(Expression<Func<T, bool>> predicate);
int Save(T entity);
void Insert(T entity);
int SaveAll(List<T> entity);
int UpdateAll(List<T> entities);
int Recreate(List<T> entity);
int Recreate(List<T> oldEntities, List<T> newEntities);
int SaveChanges();
bool Delete(T entity);
int Delete(Expression<Func<T, bool>> predicate);
/// <summary>
/// Add entity to DbSet
/// </summary>
/// <param name="entity">Entity to add in DbSet</param>
void Add(T entity);
/// <summary>
/// Add entity collection to DbSet.
/// </summary>
/// <param name="entities"></param>
void AddRange(IEnumerable<T> entities);
void Remove(T entity);
int RemoveRange(IEnumerable<T> entities);
void BlukInsert(IEnumerable<T> entities);
T FinedOneInclude(Expression<Func<T, bool>> predicate, params string[] include);
IQueryable<T> FilterWithInclude(Expression<Func<T, bool>> predicate, params string[] include);
Task<int> SaveAsync(T entity);
Task<bool> DeleteAsync(T entity);
Task<bool> DeleteAsync(Expression<Func<T, bool>> predicate);
Task<int> CountAsync();
Task<int> SaveAllAsync(List<T> entity);
Task<int> CountAsync(Expression<Func<T, bool>> predicate);
Task<bool> ExistsAsync(Expression<Func<T, bool>> predicate);
Task<T> FindOneAsync(Expression<Func<T, bool>> predicate);
Task<T> FindOneAsync(Expression<Func<T, bool>> predicate, List<string> includeProperties);
Task<ICollection<T>> FilterAsync(Expression<Func<T, bool>> predicate);
Task<int> SaveChangeAsync();
}
Repository.cs
public abstract class Repository<TDbContext, TEntity> : IRepository<TEntity>
where TEntity : class
where TDbContext : DbContext
{
public readonly TDbContext context;
private readonly DbSet<TEntity> dbSet;
protected Repository(TDbContext context)
{
this.context = context;
dbSet = this.context.Set<TEntity>();
context.Configuration.LazyLoadingEnabled = false;
context.Configuration.ProxyCreationEnabled = false;
}
/// <summary>
/// Find entity based on lamda-expression
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
public virtual TEntity FindOne(Expression<Func<TEntity, bool>> predicate)
{
return dbSet.FirstOrDefault(predicate);
}
public virtual TEntity FindOne(Expression<Func<TEntity, bool>> predicate, List<string> includeProperties)
{
IQueryable<TEntity> query = dbSet.Where(predicate);
if (includeProperties != null)
{
foreach (var name in includeProperties)
{
query = query.Include(name);
}
}
return query.FirstOrDefault();
}
/// <summary>
/// Check entity exists or not based on lamda-expression
/// </summary>
/// <param name="predicate">Expression to match</param>
/// <returns></returns>
public virtual bool Exists(Expression<Func<TEntity, bool>> predicate)
{
return dbSet.Any(predicate);
}
public virtual IQueryable<TEntity> AsQueryable()
{
return dbSet.AsQueryable();
}
/// <summary>
/// Filters a sequence of values based on a predicate.
/// </summary>
/// <param name="predicate">A function to test each element for a condition.</param>
/// <returns>An System.Linq.IQueryable`1 that contains elements from the input sequence that
/// satisfy the condition specified by predicate.
/// </returns>
public IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> predicate)
{
return dbSet.Where(predicate);
}
public virtual int Count()
{
return dbSet.Count();
}
public virtual int Count(Expression<Func<TEntity, bool>> predicate)
{
return dbSet.Count(predicate);
}
public virtual int Save(TEntity entity)
{
DbEntityEntry<TEntity> entry = context.Entry(entity);
if (entry.State == EntityState.Detached)
{
dbSet.Add(entity);
entry.State = EntityState.Added;
}
else
{
dbSet.Attach(entity);
entry.State = EntityState.Modified;
}
try
{
return context.SaveChanges();
}
catch
{
ClearEntityState();
throw;
}
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
SaveChanges();
}
public virtual int SaveAll(List<TEntity> entity)
{
dbSet.AddRange(entity);
return SaveChanges();
}
public virtual int UpdateAll(List<TEntity> entities)
{
foreach (TEntity entity in entities)
{
DbEntityEntry<TEntity> entry = context.Entry(entity);
dbSet.Attach(entity);
entry.State = EntityState.Modified;
}
return SaveChanges();
}
public virtual int Recreate(List<TEntity> entity)
{
DbSet<TEntity> objects = dbSet;
dbSet.RemoveRange(objects);
dbSet.AddRange(entity);
return SaveChanges();
}
public virtual int Recreate(List<TEntity> oldEntities, List<TEntity> newEntities)
{
dbSet.RemoveRange(oldEntities);
dbSet.AddRange(newEntities);
return SaveChanges();
}
public virtual bool Delete(TEntity entity)
{
dbSet.Remove(entity);
return SaveChanges() > 0;
}
/// <summary>
/// Will be used for DeleteALL
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
public virtual int Delete(Expression<Func<TEntity, bool>> predicate)
{
IQueryable<TEntity> objects = Where(predicate);
dbSet.RemoveRange(objects);
return SaveChanges();
}
/// <summary>
/// Save all changes in DbContext
/// </summary>
/// <returns></returns>
public int SaveChanges()
{
try
{
return context.SaveChanges();
}
catch
{
ClearEntityState();
throw;
}
}
private void ClearEntityState()
{
List<DbEntityEntry> changedEntries = context.ChangeTracker.Entries().Where(x => x.State != EntityState.Unchanged).ToList();
foreach (var entry in changedEntries.Where(x => x.State == EntityState.Modified))
{
entry.CurrentValues.SetValues(entry.OriginalValues);
entry.State = EntityState.Unchanged;
}
foreach (var entry in changedEntries.Where(x => x.State == EntityState.Added))
{
entry.State = EntityState.Detached;
}
foreach (var entry in changedEntries.Where(x => x.State == EntityState.Deleted))
{
entry.State = EntityState.Unchanged;
}
}
/// <summary>
/// Add entity to DbSet. SaveChanges requires to update database.
/// </summary>
/// <param name="entity">Entity to add in DbSet</param>
public virtual void Add(TEntity entity)
{
dbSet.Add(entity);
}
/// <summary>
/// Add entity collection to DbSet. SaveChanges requires to update database.
/// </summary>
/// <param name="entities"></param>
public virtual void AddRange(IEnumerable<TEntity> entities)
{
dbSet.AddRange(entities);
}
/// <summary>
/// Remove entity from DbSet. SaveChanges requires to update database.
/// </summary>
/// <param name="entity">Entity to remove from DbSet</param>
public virtual void Remove(TEntity entity)
{
dbSet.Remove(entity);
}
public virtual void BlukInsert(IEnumerable<TEntity> entities)
{
bool autoDetectChangesEnabled = context.Configuration.AutoDetectChangesEnabled;
bool validateOnSaveEnabled = context.Configuration.ValidateOnSaveEnabled;
context.Configuration.AutoDetectChangesEnabled = false;
context.Configuration.ValidateOnSaveEnabled = false;
dbSet.AddRange(entities);
SaveChanges();
context.Configuration.AutoDetectChangesEnabled = autoDetectChangesEnabled;
context.Configuration.ValidateOnSaveEnabled = validateOnSaveEnabled;
}
public virtual IQueryable<TEntity> GetAllInclude(params string[] include)
{
IQueryable<TEntity> query = this.dbSet.AsNoTracking();
query = include.Aggregate(query, (current, inc) => current.Include(inc));
return query.AsQueryable();
}
public virtual TEntity FinedOneInclude(Expression<Func<TEntity, bool>> predicate, params string[] include)
{
IQueryable<TEntity> query = this.dbSet.AsNoTracking();
query = include.Aggregate(query, (current, inc) => current.Include(inc));
return query.FirstOrDefault(predicate);
}
public virtual IQueryable<TEntity> FilterWithInclude(Expression<Func<TEntity, bool>> predicate, params string[] include)
{
IQueryable<TEntity> query = this.dbSet.AsNoTracking();
query = include.Aggregate(query, (current, inc) => current.Include(inc));
return query.Where(predicate).AsQueryable();
}
public virtual Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate)
{
return dbSet.CountAsync(predicate);
}
public virtual Task<int> CountAsync()
{
return dbSet.CountAsync();
}
public async virtual Task<int> SaveChangeAsync()
{
try
{
return await context.SaveChangesAsync();
}
catch (Exception e)
{
ClearEntityState();
throw;
}
}
public virtual Task<int> SaveAsync(TEntity entity)
{
DbEntityEntry<TEntity> entry = context.Entry(entity);
if (entry.State == EntityState.Detached)
{
dbSet.Add(entity);
entry.State = EntityState.Added;
}
else
{
dbSet.Attach(entity);
entry.State = EntityState.Modified;
}
try
{
return SaveChangeAsync();
}
catch
{
ClearEntityState();
throw;
}
}
public virtual Task<TEntity> FindOneAsync(Expression<Func<TEntity, bool>> predicate)
{
return dbSet.FirstOrDefaultAsync(predicate);
}
public Task<TEntity> FindOneAsync(Expression<Func<TEntity, bool>> predicate, List<string> includeProperties)
{
IQueryable<TEntity> query = this.dbSet.AsNoTracking();
query = includeProperties.Aggregate(query, (current, inc) => current.Include(inc));
return query.FirstOrDefaultAsync(predicate);
}
public virtual Task<bool> ExistsAsync(Expression<Func<TEntity, bool>> predicate)
{
return dbSet.AnyAsync(predicate);
}
public async virtual Task<bool> DeleteAsync(TEntity entity)
{
dbSet.Remove(entity);
try
{
var effectedRows = await SaveChangeAsync();
return effectedRows > 0;
}
catch (Exception e)
{
throw new Exception("Someting went wrong. Please first delete family information");
}
}
public async virtual Task<bool> DeleteAsync(Expression<Func<TEntity, bool>> predicate)
{
IQueryable<TEntity> objects = Where(predicate);
dbSet.RemoveRange(objects);
return await SaveChangeAsync() > 0;
}
public async virtual Task<ICollection<TEntity>> FilterAsync(Expression<Func<TEntity, bool>> predicate)
{
return await dbSet.Where(predicate).ToListAsync();
}
public Task<int> SaveAllAsync(List<TEntity> entity)
{
dbSet.AddRange(entity);
return SaveChangeAsync();
}
public int RemoveRange(IEnumerable<TEntity> entities)
{
dbSet.RemoveRange(entities);
return SaveChanges();
}
}
SSRepository.cs
public class SSRepository<T> : Repository<SSDBEntities, T>, ISSRepository<T>
where T : class
{
internal SqlConnection Connection;
public SSRepository(SSDBEntities context) : base(context)
{
Connection = context.Database.Connection as SqlConnection;
}
public DataTable ExecWithStoreProcedure(string query, IDictionary<string, object> values)
{
using (Connection)
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = query;
foreach (KeyValuePair<string, object> item in values)
{
cmd.Parameters.AddWithValue("#" + item.Key, item.Value);
}
DataTable table = new DataTable();
using (var reader = cmd.ExecuteReader())
{
table.Load(reader);
return table;
}
}
}
public DataTable ExecWithSqlQuery(string query)
{
try
{
Connection.Open();
SqlCommand cmd = new SqlCommand(query, Connection);
DataTable dt = new DataTable();
SqlDataAdapter dataAdapter = new SqlDataAdapter(cmd);
dataAdapter.Fill(dt);
return dt;
}
catch
{
throw new Exception();
}
finally
{
if
(Connection.State == ConnectionState.Open)
{
Connection.Close();
}
}
}
public int ExecNoneQuery(string query)
{
try
{
Connection.Open();
using (SqlCommand cmd = new SqlCommand(query, Connection))
{
return cmd.ExecuteNonQuery();
}
}
catch
{
throw new Exception();
}
finally
{
if
(Connection.State == ConnectionState.Open)
{
Connection.Close();
}
}
}
}
Can anyone help me to solve this issue?

In this case the error is telling you exactly what the issue is - your controller does not have a constructor that takes zero parameters. e.g.:
public ProductController()
{
}
By default, the application does not know how to provide an IProductService as a parameter.
If you create a default constructor you could create a new IProductService in it rather than accepting it as a parameter, or as the property initialisation.
If you do not want to have a parameterless constructor you could use some form of dependency injection, which would have been configured to know how to create an IProductService and provide it to your existing constructor.

Related

error 'The operation cannot be completed because the DbContext has been disposed.'

I am using generic repository and unit of work in asp.net MVC. when I want to access the context in controller I get this error:
'The operation cannot be completed because the DbContext has been disposed.'
however when I comment this line:
'Database.SetInitializer(new MigrateDatabaseToLatestVersion());'
in Global.asax the error will fix. but as soon as i uncomment that line the error still happening.
here is generic repository:
public class GenericRepository<TEntity> where TEntity : class
{
internal ZarinParse_Context context;
internal DbSet<TEntity> dbSet;
public GenericRepository(ZarinParse_Context context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters)
{
return dbSet.SqlQuery(query, parameters).ToList();
}
public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
public virtual void Update(TEntity entity)
{
dbSet.Attach(entity);
context.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(object id)
{
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TEntity entity)
{
if (context.Entry(entity).State == EntityState.Detached)
{
dbSet.Attach(entity);
}
dbSet.Remove(entity);
}
}
and unit of work:
public class UnitOfWork : IDisposable
{
private ZarinParse_Context context;
private RoleRepository roleRepository;
private UserRepository userRepository;
private UserRoleRepository userRoleRepository;
public UnitOfWork()
{
context = new ZarinParse_Context();
}
public RoleRepository RoleRepository
{
get
{
if (this.roleRepository == null)
{
this.roleRepository = new RoleRepository(context);
}
return roleRepository;
}
}
public UserRepository UserRepository
{
get
{
if (this.userRepository == null)
{
this.userRepository = new UserRepository(context);
}
return userRepository;
}
}
public UserRoleRepository UserRoleRepository
{
get
{
if (this.userRoleRepository == null)
{
this.userRoleRepository = new UserRoleRepository(context);
}
return userRoleRepository;
}
}
public void Save()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
RoleRepository Class:
public class RoleRepository : GenericRepository<Role>
{
public RoleRepository(ZarinParse_Context context)
: base(context)
{
}
}
my Context:
public class ZarinParse_Context : DbContext
{
public IDbSet<User> Users { get; set; }
public IDbSet<Role> Roles { get; set; }
public IDbSet<UserRole> UserRoles { get; set; }
public IDbSet<Product> Products { get; set; }
public IDbSet<Tag> Tags { get; set; }
public IDbSet<TagProduct> TagProducts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new UserConfig());
modelBuilder.Configurations.Add(new RoleConfig());
modelBuilder.Configurations.Add(new UserRoleConfig());
modelBuilder.Configurations.Add(new ProductConfig());
modelBuilder.Configurations.Add(new TagConfig());
modelBuilder.Configurations.Add(new TagProductConfig());
}
}
my Controller:
public class HomeController : Controller
{
UnitOfWork unitOfWork = new UnitOfWork();
public ActionResult Index()
{
var model = new Role() { Name = "User" };
unitOfWork.RoleRepository.Insert(model);
unitOfWork.Save();
return View();
}
protected override void Dispose(bool disposing)
{
unitOfWork.Dispose();
base.Dispose(disposing);
}
}
and Global.asax File:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ZarinParse_Context, Configuration>());
}
}
and Configuration :
public class Configuration : DbMigrationsConfiguration<ZarinParse_Context>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
AutomaticMigrationDataLossAllowed = false;
ContextKey = "ZarinParse.DomainClasses.Context.ZarinParse_Context";
}
protected override void Seed(ZarinParse_Context context)
{
InitializeAdmin(context: context,
roleName: "Admin",
userName: "soheil91141121#gmail.com",
password: "stb_91141121",
fullName: "سهیل تقی زاده بنگر",
mobileNumber: "09356336121",
newsEamilEnabled: true);
}
private void InitializeAdmin(ZarinParse_Context context, string roleName, string userName, string password, string fullName, bool newsEamilEnabled, string mobileNumber)
{
//Create Role Admin if it does not exist
var roleExist = context.Roles.Any(p => p.Name == roleName);
if (!roleExist)
{
var role = Role.Create();
role.Name = roleName;
context.Roles.Add(role);
context.SaveChanges();
}
//Create User if it does not exist
var userExist = context.Users.Any(p => p.UserName == userName);
if (!userExist)
{
var user = User.Create();
user.UserName = userName;
user.Email = userName;
user.Password = password.Encrypt();
user.FullName = fullName;
user.NewsEmailEnabled = newsEamilEnabled;
user.MobileNumber = mobileNumber;
context.Users.Add(user);
context.SaveChanges();
}
//Create UserRole if it does not exist
var role2 = context.Roles.Single(p => p.Name == roleName);
var user2 = context.Users.Single(p => p.UserName == userName);
var userRoleExist = context.UserRoles.Any(p => p.RoleId == role2.RoleId && p.UserId == user2.UserId);
if (!userRoleExist)
{
var userRole = UserRole.Create();
userRole.Role = role2;
userRole.User = user2;
context.UserRoles.Add(userRole);
context.SaveChanges();
}
context.Dispose();
}
}
The last line of InitializeAdmin disposes a context that is passed into the method.
Only dispose of objects that you have created, since you own the object's lifetime.
In other words, don't dispose of objects you don't own.

How many repositories is too many?

We are getting ready to modularize a large enterprise application that is currently using a dying stack of technologies. My question is in the Repository/Unit of Work pattern, how many Repositories can you have in a unit of work? Say for example we create a UnitOfWork on a single DbContext that exposes 50+ repository entities. Will this cause performance problems?
We were looking at maybe splitting it up so that each schema has it's own DbContext but this seems to add a lot of complexity and then doesn't allow for easy joining of data between the schemas. I feel like creating everything under one context/unit of work is the best answer for ease of use and maintainability but I am concerned performance may be a problem.
public class UnitOfWork : IUnitOfWork
{
private readonly AppContext _context;
public UnitOfWork(AppContext context)
{
_context = context;
Courses = new CourseRepository(_context);
Authors = new AuthorRepository(_context);
...
...
// Will lots of repositories here cause a performance problem?
...
...
...
...
...
}
public ICourseRepository Courses { get; private set; }
public IAuthorRepository Authors { get; private set; }
...
...
public int Complete()
{
return _context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
It's a few years old now but I've used a UnitOfWork with a GenericRepository and not suffered any major performance issues. This is hooked into over 100 DB tables of a busy website.
That said, the website in question also employs the Dapper Micro-ORM throughout as it's very fast and gives more control on complex operations. For CRUD though, the setup below works well for me.
Unit Of Work
public class UnitOfWork :IDisposable
{
private DbContext _db = new DbContext();
private GenericRepository<Table1> table1Repository;
private GenericRepository<Table2> table2Repository;
private GenericRepository<Table3> table3Repository;
...
private GenericRepository<TableN> tableNRepository;
public GenericRepository<Table1> Table1Repository
{
get
{
if (this.table1Repository == null)
{
this.table1Repository = new GenericRepository<Table1>(_db);
}
return table1Repository;
}
}
public void Save()
{
_db.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_db.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Generic Repository
public class GenericRepository<TEntity> where TEntity :class
{
internal DbContext _db;
internal DbSet<TEntity> dbSet;
public GenericRepository(DbContext _db)
{
this._db = _db;
this.dbSet = _db.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query);
}
else
{
return query;
}
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
public virtual void Delete(object id)
{
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TEntity entityToDelete)
{
if (_db.Entry(entityToDelete).State == EntityState.Detached)
{
dbSet.Attach(entityToDelete);
}
dbSet.Remove(entityToDelete);
}
public virtual void Update(TEntity entityToUpdate)
{
dbSet.Attach(entityToUpdate);
_db.Entry(entityToUpdate).State = EntityState.Modified;
}
}
Usage
var unitOfWork = new UnitOfWork();
List<Table1> list = unitOfWork.Table1Repository.Get(n => n.addedOn <= DateTime.Now);
Table1 item = unitOfWork.Table1Repository.GetById(1);
unitOfWork.Table1Repository.Insert(object);
unitOfWork.Save();
unitOfWork.Table1Repository.Update(object);
unitOfWork.Save();
unitOfWork.Table1Repository.Delete(1);
unitOfWork.Save();
unitOfWork.Table1Repository.Delete(object);
unitOfWork.Save();

how to delete all records in a particular table before excel import using ASP.NET MVC

Please How do I delete all existing records, refresh and reset the table before I Save new records. I want to do it from my controller.
Controller
public ActionResult Create(ITEM items)
{
try
{
// TODO: Add insert logic here
if (ModelState.IsValid)
{
_itemsService.AddCity(thirdparties);
return RedirectToAction("Index");
}
}
catch
{
ModelState.AddModelError("", "We cannot add this items. Verify your data entries !");
}
return View(items);
}
I have an N-Tier layer
Infrastructure
Repository
Web(Presentation
Infrastructure
public interface IRepository<T> where T : class
{
IEnumerable<T> FindAll(Expression<Func<T, bool>> predicate = null);
T FindById(object id);
T FindByEntity(T entity);
T FindByString(object strValue);
void Add(T entity);
void Remove(T entity);
}
public abstract class Repository<T> : IRepository<T> where T : class
{
public virtual IEnumerable<T> FindAll(Expression<Func<T, bool>> predicate = null)
{
IQueryable<T> items = DataContextFactory.AdminEntities.Set<T>();
return (predicate == null) ? items : items.Where(predicate);
}
public abstract T FindById(object id);
public abstract T FindByString(object strValue);
public abstract T FindByEntity(T entity);
public virtual void Add(T entity)
{
DataContextFactory.AdminEntities.Set<T>().AddOrUpdate(entity);
DataContextFactory.AdminEntities.SaveChanges();
}
public virtual void Remove(T entity)
{
T item = FindByEntity(entity);
if (item != null)
DataContextFactory.AdminEntities.Set<T>().Remove(item);
DataContextFactory.AdminEntities.SaveChanges();
}
}
Repository
public class CitiesManager: ICitiesManager
{
private readonly IRepository<CITIES> _citiesRepository;
public CitiesManager(IRepository<CITIES> citiesRepository)
{
_citiesRepository = citiesRepository;
}
public CITIES City(Int32 cityID)
{
return _citiesRepository.FindById(cityID);
}
public IEnumerable<CITIES> Cities()
{
return _citiesRepository.FindAll().ToList();
}
public void AddCity(CITIES cities)
{
_citiesRepository.Add(cities);
}
public void RemoveCity(Int32 cityID)
{
_citiesRepository.Remove(City(cityID));
}
}
My model classes are in the infrastucture
Infrastructure --> Repository --> Web

An entity object cannot be referenced by multiple instances of IEntityChangeTracker when saving changes

I have two domain objects, both identical but with different PK properties:
public partial class Maintenance : MaintenanceBase
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int MaintenanceId { get; set; }
public virtual Employee Employee { get; set; }
}
public partial class MyMaintenance : MaintenanceBase
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int RowId { get; set; }
public virtual Employee Employee { get; set; }
}
The rest of the properties are inherited from a base class. The problem I am having is when try to call save changes in my post controller, I am getting the following error:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
This is (basically) my controller method:
[HttpPost]
public ActionResult SubmitMyMaintenance(IList<MyMaintenance> myMaintenanceList, string userName)
{
foreach (var result in myMaintenanceList)
{
var m = iMyMaintenanceRepository.GetSingle(result.RowId);
Maintenance maintenance = new Maintenance();
// Use Injector to handle mapping between viewmodel and model
maintenance.InjectFrom(m);
try
{
if (ModelState.IsValid)
{
// save the maintenance item
iMaintenanceRepository.Add(maintenance);
iMaintenanceRepository.Save();
// delete the item in MyMaintenance
iMyMaintenanceRepository.Delete(m);
iMyMaintenanceRepository.Save();
}
}
catch (DataException ex)
{
message = ex.InnerException.ToString();
}
}
// refresh the view
var mvm = new MyMaintenanceListViewModel
{
MyMaintenanceList = iMyMaintenanceRepository.FindBy(v => v.CreatedBy.Equals(userName)).ToList(),
Message = "Your maintenance items were successfully added."
};
return View("MyMaintenance", mvm);
}
I suspect this is because I have instances of respositories (iMaintenanceRepository & iMyMaintenanceRepository) for both domain objects in the same controller post method, and both have a reference to the Employee entity.
For instance, when I dispose the iMyMaintenanceRepository and create a new instance (before refreshing the view at the end), I get en error about inserting a null value in the Employee table, which I am not inserting anything. That is the reason I suspect the Employee entity exists in two different data contexts. I am not sure how to resolve it though. None of the solutions I have found seem to apply and I am thinking it is more of an implementation problem on my part.
EDIT: Repositories
namespace EMMS.Models.Interfaces
{
public interface IMyMaintenanceRepository : IGenericRepository<MyMaintenance>
{
MyMaintenance GetSingle(int RowId);
}
}
namespace EMMS.Models.Repositories
{
public class MyMaintenanceRepository : GenericRepository<AppDBContext, MyMaintenance>, IMyMaintenanceRepository
{
public MyMaintenance GetSingle(int RowId)
{
var query = GetAll().FirstOrDefault(x => x.RowId == RowId);
return query;
}
}
}
namespace EMMS.ViewModels.Repositories
{
public class GenericRepository<C, T> : IDisposable, IGenericRepository<T>
where T : class
where C : DbContext, new()
{
private C _entities = new C();
public C Context
{
get { return _entities; }
set { _entities = value; }
}
public virtual IQueryable<T> GetAll()
{
IQueryable<T> query = _entities.Set<T>();
return query;
}
public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
IQueryable<T> query = _entities.Set<T>().Where(predicate);
return query;
}
// enforce referential itegrity
public bool ValueInUse(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
IQueryable<T> query = _entities.Set<T>().Where(predicate);
int count = query.Count();
return count > 0 ? true : false;
}
public virtual void Add(T entity)
{
_entities.Set<T>().Add(entity);
}
public virtual void Delete(T entity)
{
_entities.Entry(entity).State = System.Data.EntityState.Deleted;
}
public virtual void Edit(T entity)
{
_entities.Entry(entity).State = System.Data.EntityState.Modified;
}
public virtual void Save()
{
_entities.SaveChanges();
}
private bool disposed = false; // to detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
if (_entities != null)
{
_entities.Dispose();
}
}
disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
namespace EMMS.ViewModels.Interfaces
{
public interface IGenericRepository<T> where T : class
{
IQueryable<T> GetAll();
IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
bool ValueInUse(System.Linq.Expressions.Expression<Func<T, bool>> predicate);
void Add(T entity);
void Delete(T entity);
void Edit(T entity);
void Save();
void Dispose();
}
}
You're absolute correct about the issue. Actually, in particular, it's because each repository has it's own instance of your context object, and you're trying to pass an Employee that was originally retrieved via one instance and saving it via different instance.
The easiest solution is to track all like things in one repository. In other words, just use one MaintenanceRepository can have calls to return both Maintenance and MyMaintenance. Though that stretches the idea of a "repository" a bit. This is why repositories are typically combined with a Unit of Work class, which would house the context for the repositories to share. However, at that point, you're basically just recreating the structure Entity Framework already implements. So, holding everything in just one "repository" makes more sense, but now you're really talking about a "service" pattern rather than a repository pattern. It's just semantics though.
UPDATE
Disclaimer: This is what I'm using currently in a project and it works for me. This may not be the best practice and reasonable people could very well disagree with my approach.
IService Interface
public interface IService<TContext, TEntity>
where TContext : DbContext
where TEntity : class
{
IEnumerable<TEntity> GetAll(
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "");
IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "");
TEntity GetById(int id, string includeProperties = "");
TEntity GetOne(
Expression<Func<TEntity, bool>> filter = null,
string includeProperties = "");
TEntity GetFirst(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "");
TEntity GetLast(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "");
void Create(TEntity entity);
void Update(TEntity entity);
void Delete(int id);
void Delete(TEntity entity);
int Count(Expression<Func<TEntity, bool>> filter = null);
bool Any(Expression<Func<TEntity, bool>> filter = null);
}
Service, Implementation of IService
public class Service<TContext, TEntity> : IService<TContext, TEntity>
where TContext : DbContext
where TEntity : class
{
internal TContext context;
internal DbSet<TEntity> dbSet;
public Service(TContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> GetAll(
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
return Get(null, orderBy, includeProperties);
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.Distinct().ToList();
}
}
public virtual TEntity GetById(int id, string includeProperties = "")
{
return dbSet.Find(id);
}
public virtual TEntity GetOne(
Expression<Func<TEntity, bool>> filter,
string includeProperties = "")
{
return Get(filter, null, includeProperties).SingleOrDefault();
}
public virtual TEntity GetFirst(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
return Get(filter, orderBy, includeProperties).FirstOrDefault();
}
public virtual TEntity GetLast(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
return Get(filter, orderBy, includeProperties).LastOrDefault();
}
public virtual void Create(TEntity entity)
{
dbSet.Add(entity);
}
public virtual void Delete(int id)
{
var entity = GetById(id);
Delete(entity);
}
public virtual void Delete(TEntity entity)
{
if (context.Entry(entity).State == EntityState.Detached)
{
dbSet.Attach(entity);
}
dbSet.Remove(entity);
}
public virtual void Update(TEntity entity)
{
if (context.Entry(entity).State == EntityState.Detached)
{
dbSet.Attach(entity);
}
context.Entry(entity).State = EntityState.Modified;
}
public virtual int Count(Expression<Func<TEntity, bool>> filter = null)
{
return Get(filter).Count();
}
public virtual bool Any(Expression<Func<TEntity, bool>> filter = null)
{
return Count(filter) > 0;
}
}
ServiceGroup, Abstract container for services
public abstract class ServiceGroup<TContext> : IDisposable
where TContext : DbContext
{
protected TContext context;
public virtual void Save()
{
try
{
context.SaveChanges();
}
catch (DbEntityValidationException validationException)
{
string validationErrorMessage = DbEntityValidationMessageParser.GetErrorMessage(validationException);
Console.WriteLine(validationErrorMessage);
}
}
#region Disposable
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public virtual void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
So, the way I use this all is whenever I want to create a collection of like things to work with, I subclass ServiceGroup like so:
public class SampleService : ServiceGroup<MyDbContext>
{
public SampleService()
{
this.context = new MyDbContext();
}
private Service<MyDbContext, SomeModel> someModels;
public Service<MyDbContext, SomeModel> SomeModels
{
get
{
if (someModels == null)
{
someModels = new Service<MyDbContext, SomeModel>(context);
}
return someModels;
}
}
private Service<MyDbContext, AnotherModel> anotherModels;
public Service<MyDbContext, AnotherModel> AnotherModels
{
get
{
if (anotherModels == null)
{
anotherModels = new Service<MyDbContext, AnotherModel>(context);
}
return anotherModels;
}
}
// rinse and repeat
}
This makes sure everything is using the same context instance. So to actually use it, you just do:
var service = new SampleService();
someModels = service.SomeModels.GetAll();
So I was searching the web for a complete example of a code first MVC implementation with repositories, unit of work, viewmodels, etc, and I found exactly what I was looking for here:
EFMVC - ASP.NET MVC 4, Entity Framework 5 Code First and Windows Azure
This is a great demo web app that does everything I need from an architectural standpoint. I don't understand half of it, though, (yet) and it took me about 4 hours of retooling my app, but man was it worth it! It also solved my IEntityChangeTracker error.

MVC3 EF Unit of Work + Generic Repository + Ninject

I'm new to MVC3 and have been following the awesome tutorials on the asp.net website. However, I can't quite wrap my head around how to use Unit of Work and Generic Repository patterns with Ninject. I used this tutorial as a starting point: http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
Without using interfaces, I know I can implement it like so:
Generic Repository:
public class GenericRepository<TEntity> : IGenericRepository<TEntity>
where TEntity : class
{
internal MyContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(MyContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
}
Unit of Work:
private MyContext context = new MyContext();
private GenericRepository<Student> studentRepository;
private GenericRepository<Course> courseRepository;
public GenericRepository<Student> StudentRepository
{
if (this.studentRepository == null)
{
this.studentRepository = new GenericRepository<Student>(context);
}
return studentRepository;
}
public GenericRepository<Course> CourseRepository
{
if (this.courseRepository == null)
{
this.courseRepository = new GenericRepository<Course>(context);
}
return courseRepository;
}
This setup allows me to pass the same context to all repositories, and then call a single Save() function to commit the changes.
I know I can use an interface IGenericRepository<TEntity> and the concrete implementation GenericRepository<TEntity> and then bind them using Ninject:
kernel.Bind(typeof(IGenericRepository<>)).To(typeof(GenericRepository<>));
But how would I go about setting up my IUnitOfWork and UnitOfWork to ensure that all my repositories share a single database context? Am I even doing it right in the first place? I've searched around but all I seem to find are tutorials that only use generic repositories without a unit of work.
Your base Repo:
public class BaseRepository<TObject> : IRepository<TObject>
where TObject : class
{
public BaseRepository(IUnitOfWork unitOfWork)
{
if (unitOfWork == null) throw new ArgumentException("unitOfWork");
UnitOfWork = unitOfWork;
}
protected DbSet<TObject> DbSet
{
get
{
return Context.Set<TObject>();
}
}
public void Dispose()
{
if (sharedContext && (Context != null))
Context.Dispose();
}
public virtual IQueryable<TObject> All()
{
return DbSet.AsQueryable();
}
public virtual IQueryable<TObject>
Filter(Expression<Func<TObject, bool>> predicate)
{
return DbSet.Where(predicate).AsQueryable<TObject>();
}
public virtual IQueryable<TObject> Filter<Key>(Expression<Func<TObject, Key>> sortingSelector, Expression<Func<TObject, bool>> filter, out int total,
SortingOrders sortby = SortingOrders.Asc, int index = 0, int size = 50)
{
int skipCount = index * size;
var _resultSet = filter != null ? DbSet.Where(filter).AsQueryable() : DbSet.AsQueryable();
total = _resultSet.Count();
_resultSet = sortby == SortingOrders.Asc ? _resultSet.OrderBy(sortingSelector).AsQueryable() : _resultSet.OrderByDescending(sortingSelector).AsQueryable();
_resultSet = skipCount == 0 ? _resultSet.Take(size) : _resultSet.Skip(skipCount).Take(size);
return _resultSet;
}
public bool Contains(Expression<Func<TObject, bool>> predicate)
{
return DbSet.Count(predicate) > 0;
}
public virtual TObject Find(params object[] keys)
{
return DbSet.Find(keys);
}
public virtual TObject Find(Expression<Func<TObject, bool>> predicate)
{
return DbSet.FirstOrDefault(predicate);
}
public virtual TObject Create(TObject TObject, bool SaveChanges = true)
{
var newEntry = DbSet.Add(TObject);
if (!sharedContext && SaveChanges)
Context.SaveChanges();
return newEntry;
}
public virtual int Count
{
get
{
return DbSet.Count();
}
}
public virtual int Delete(TObject TObject)
{
DbSet.Remove(TObject);
if (!sharedContext)
return Context.SaveChanges();
return 0;
}
public virtual int Update(TObject TObject, bool SaveChanges = true)
{
var entry = Context.Entry(TObject);
DbSet.Attach(TObject);
entry.State = EntityState.Modified;
if (!sharedContext && SaveChanges)
return Context.SaveChanges();
return 0;
}
public virtual int Delete(Expression<Func<TObject, bool>> predicate)
{
var objects = Filter(predicate);
foreach (var obj in objects)
DbSet.Remove(obj);
if (!sharedContext)
return Context.SaveChanges();
return 0;
}
/// <summary>
/// Sets the state of an entity.
/// </summary>
/// <param name="entity">object to set state.</param>
/// <param name="entityState"><see cref="EntityState"/></param>
protected virtual void SetEntityState(object entity, EntityState entityState)
{
Context.Entry(entity).State = entityState;
}
/// <summary>
///
/// </summary>
/// <param name="entity"></param>
protected virtual void Attach(object entity)
{
if (Context.Entry(entity).State == EntityState.Detached)
Context.Entry(entity).State = EntityState.Modified;
}
protected virtual void Detach(object entity)
{
Context.Entry(entity).State = EntityState.Detached;
}
public void SubmitChanges()
{
UnitOfWork.SaveChanges();
}
#region Properties
private bool sharedContext { get; set; }
/// <summary>
/// Unit of work controlling this repository.
/// </summary>
protected IUnitOfWork UnitOfWork { get; set; }
/// <summary>
/// Provides access to the ef context we are working with
/// </summary>
internal IMyContext Context
{
get
{
return (IMyContext)UnitOfWork;
}
}
#endregion
}
Notice Context is an interface implementing UnitOfWork.
Your context interface:
public interface IMyContext : IDbContext
{
DbSet<Sometype> SomeProperty { get; set; }
...
}
Your IDbContext interface:
public interface IDbContext
{
DbChangeTracker ChangeTracker { get; }
DbContextConfiguration Configuration { get; }
Database Database { get; }
void Dispose();
void Dispose(bool disposing);
DbEntityEntry Entry(object entity);
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
bool Equals(object obj);
int GetHashCode();
Type GetType();
IEnumerable<DbEntityValidationResult> GetValidationErrors();
void OnModelCreating(DbModelBuilder modelBuilder);
int SaveChanges();
DbSet<TEntity> Set<TEntity>() where TEntity : class;
DbSet Set(Type entityType);
bool ShouldValidateEntity(DbEntityEntry entityEntry);
string ToString();
DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items);
}
Then the actual context implementation:
public class MyContext : DbContext, IUnitOfWork, IMyContext
{
//public MyContext()
//{
// Database.SetInitializer<ReconContext>(null);
//}
public ReconContext()
: base("Name=ReconContext")
{
((IObjectContextAdapter)this).ObjectContext.ContextOptions.ProxyCreationEnabled = false;
}
public DbSet<SomeType> SomeProperty { get; set; }
....
public new void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new SomePropertyMap());
.....
base.OnModelCreating(modelBuilder);
}
int IUnitOfWork.SaveChanges()
{
return base.SaveChanges();
}
void IDisposable.Dispose()
{
base.Dispose();
}
public new void Dispose(bool disposing)
{
base.Dispose(disposing);
}
public new bool ShouldValidateEntity(DbEntityEntry entityEntry)
{
return base.ShouldValidateEntity(entityEntry);
}
public new DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
return base.ValidateEntity(entityEntry, items);
}
}
Then in your ninject config you simply do:
kernel.Bind<IUnitOfWork<MyContext>>().To<MyContext>().InRequestScope();

Resources