Controller with same structure not working using an interface - c#

I have created 8 models and controllers respectively for my Project using the same structure, however now this structure is not working. It is giving me this error:
The current type, HelpDesk.Contracts.Repositories.IRepositoryBase`1[HelpDesk.Model.Knowledgebase], is an interface and cannot be constructed. Are you missing a type mapping?
Here is my interface:
namespace HelpDesk.Contracts.Repositories
{
public interface IRepositoryBase<TEntity>
where TEntity : class
{
void Commit();
void Delete(object id);
void Delete(TEntity entity);
System.Linq.IQueryable<TEntity> GetAll();
System.Linq.IQueryable<TEntity> GetAll(object filter);
TEntity GetById(object id);
TEntity GetFullObject(object id);
System.Linq.IQueryable<TEntity> GetPaged(int top = 20, int skip = 0, object orderBy = null, object filter = null);
void Insert(TEntity entity);
void Update(TEntity entity);
}
}
Here is my controller:
namespace HelpDesk.WebUI.Controllers
{
public class KnowledgebaseController : Controller
{
private DataContext db = new DataContext();
IRepositoryBase<Knowledgebase> knowledgebases;
public KnowledgebaseController(IRepositoryBase<Knowledgebase> knowledgebases)
{
this.knowledgebases = knowledgebases;
}
public ActionResult ChooseSearchView()
{
string r = Session["LoggedUserRole"].ToString();
if (r == "Technician")
{
return RedirectToAction("TechKnowledgebaseSearch");
}
else
{
return RedirectToAction("UserKnowledgebaseSearch");
};
}
My DataContext:
namespace HelpDesk.Contracts.Data
{
public class DataContext : DbContext
{
/// <summary>
/// you can either pass the NAME of a connection string (e.g. from a web.
/// ), and explicitly i
/// </summary>
public DataContext() : base("HelpDesk")
{
}
/// <summary>
/// any entity to be persisted must be declared here.
/// </summary>
///
public DbSet<Category> Categories { get; set; }
public DbSet<Knowledgebase> Knowledgebases { get; set; }
public DbSet<Problem> Problems { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<Ticket> Tickets { get; set; }
public DbSet<TicketNote> TicketNotes { get; set; }
public DbSet<TicketStatus> TicketStatuses { get; set; }
public DbSet<TicketSubscription> TicketSubscriptions { get; set; }
public DbSet<User> Users { get; set; }
}
}
Here is the repositorybase:
namespace HelpDesk.Contracts.Repositories
{
public abstract class RepositoryBase<TEntity> : HelpDesk.Contracts.Repositories.IRepositoryBase<TEntity> where TEntity : class
{
internal DataContext context;
internal DbSet<TEntity> dbSet;
public RepositoryBase(DataContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual TEntity GetById(object id)
{
return dbSet.Find(id);
}
public virtual IQueryable<TEntity> GetAll()
{
return dbSet;
}
public IQueryable<TEntity> GetPaged(int top = 20, int skip = 0, object orderBy = null, object filter = null)
{
return null; // need to override in order to implement specific filtering and ordering
}
public virtual IQueryable<TEntity> GetAll(object filter)
{
return null; //need to override in order to implement specific filtering
}
public virtual TEntity GetFullObject(object id)
{
return null; //need to override in order to implement specific obect graph.
}
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(TEntity entity)
{
if (context.Entry(entity).State == EntityState.Detached)
dbSet.Attach(entity);
dbSet.Remove(entity);
}
public virtual void Delete(object id)
{
TEntity entity = dbSet.Find(id);
}
public virtual void Commit()
{
context.SaveChanges();
}
public virtual void Dispose()
{
context.Dispose();
}
}
}
Here I have a similar structured Controller that works just fine and another 7 like that:
namespace HelpDesk.WebUI.Controllers
{
public class RoleController : Controller
{
private DataContext db = new DataContext();
IRepositoryBase<Role> roles;
public RoleController(IRepositoryBase<Role> roles)
{
this.roles = roles;
}
The Exception is thrown when I click on this link:
<li>#Html.ActionLink("Knowledgebase", "ChooseSearchView", "Knowledgebase")</li>

Update your KnowledgebaseController constructor to this:
public KnowledgebaseController()
{
this.knowledgebases = new RepositoryBase<Knowledgebase>(db);
}
and remove abstract from the RepositoryBase<TEntity> class in order to make it instantiable.
Please note: This is just a quick fix. To implement a much solid architecture which facilitates easy unit testing and loosely coupled classes, I would suggest you implement a unit of work. Follow this link Repository Pattern and Unit of Work with Entity Framework in ASP.NET MVC

You can't instantiate an interface, you have to instantiate a class that implements that interface.
public class RepositoryBase<T> : IRepositoryBase
{
public RepositoryBase<T>()
{
}
...
}
Then instantiate your concrete class with that type
IRepositoryBase<Knowledgebase> knowledgebases = new RepositoryBase<Knowledgebase>();
Read more about interfaces and instantiation here: Using Interfaces

Related

DI Implementation in asp.net project

I am using ASP.Net, Entity Framwork along with Microsoft Unity Framework integration, i have below setup for the data consumption:
DataObjects:
ArticleDo - This contains all the entities needed for the database.
GenericDo - This contains all the entities which are common across project.
Dao. (Concrete classes)
ArticleDao - This contains the implemented functions specific for Articles from IArticleDao. (This inherits GenericDao, IArticleDao
GenericDao - This is an abstract class it contains the implementation of the Generic functions used across the project.
Interfaces.
IArticleDao - This contains the declaration of the Article specific functions. (this inherits IGenericDao)
IGenericDao -This contains the declaration of all the generic functions which are common across projects, like pulling in specific field from database etc. (This inherits IGenericDao
Here's the implementation:
DataObjects.
1. ArticleDo:
public class ArticleDo
{
public virtual int Id { get; set; }
public virtual int WordCount { get; set; }
public virtual string Title { get; set; }
}
2. GenericDo:
public class GenericDo
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
}
Business Layer (Concrete classes)
1. ArticleDao:
public class ArticleDao : GenericDao<ArticleDo, DataContext>, IArticleDao
{
private readonly Data.DataContext db;
public ArticleDao()
{
db = new Data.DataContext();
}
public override string Add(ArticleDo entity)
{
entity.AddedBy = Common.CurrentUsername;
db.Articles.Add(entity);
var returnVal = db.SaveChanges();
if (returnVal > 0)
return "Success";
return "Fail";
}
public List<ArticleDo> Search(string SearchTerm, int CurrentPage, out int Total)
{
SearchTerm = SearchTerm.ToLower();
var totalRecords = List().Where(x => x.ArticleId.ToString() == SearchTerm ||
(x.Title.ToString().ToLower().Contains(SearchTerm)));
Total = totalRecords.Count();
return totalRecords.Skip(CurrentPage * Common.Page_SIZE).Take(Common.Page_SIZE).ToList();
}
}
2. GenericDao:
public abstract class GenericDao<T, C> : IGenericDao<T, C> where T : class where C : DbContext, new ()
{
private readonly DataContext _db = new DataContext();
private C _entities = new C();
public virtual string Add(T entity)
{
_entities.Set<T>().Add(entity);
return "Success";
}
public virtual bool Delete(T entity)
{
_entities.Set<T>().Remove(entity);
return true;
}
public T Get(T entity)
{
var _get = _entities.Set<T>();
if (_get == null) return null;
return _get.First();
}
public virtual List<T> List()
{
return _entities.Set<T>().ToList();
}
public virtual bool Update(T entity)
{
_entities.Entry(entity).State = EntityState.Modified;
return true;
}
public T FindByProperty(string property, object value)
{
var _find = _db.Database.SqlQuery<IEnumerable<T>>(string.Format("SELECT a.* from {0} a where a.p0 = p1", typeof(T).FullName), new object[] { property, value });
if (_find != null && _find.Any())
{
return (T)_find.First();
}
return null;
}
}
DataInterfaces.
1. IArticleDao
public interface IArticleDao : IGenericDao<ArticleDo, DataContext>
{
List<ArticleDo> Search(string SearchTerm, int CurrentPage, out int Total);
}
2. IGenericDao
public interface IGenericDao : IGenericDao<GenericDo, DataContext> { }
public interface IGenericDao<T, C>
{
string Add(T entity);
bool Update(T entity);
bool Delete(T entity);
List<T> List();
T Get(T entity);
T FindByProperty(string property, object value);
}
Now before i implement the entities which would resolve the `IArticleDao` and i would be able to call my business layer functions, i tried to create concrete object directly in the page behind like:
IArticleDao dao = new ArticleDao();
Now as per my understanding, since ArticleDao is inheriting GenericDao<ArticleDo, DataContext> i should be able to access all the ArticleDo entities from the dao object, but that's not happening, could anyone please help me to achieve this, i don't want to inherit ArticleDao in ArticleDo, because that would defeat the purpose of DI integration. Also how could i use the contructor injection, do i need to create the constructor in my aspx code behind file?

Passing value to FindById method using Generic types doesn't work

I have a repository for all my entities like this :
public abstract class GenericRepository<C, T> :
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;
}
public virtual void Add(T entity)
{
_entities.Set<T>().Add(entity);
}
public virtual void Delete(T entity)
{
_entities.Set<T>().Remove(entity);
}
public virtual void Edit(T entity)
{
_entities.Entry(entity).State = System.Data.Entity.EntityState.Modified;
}
public virtual void Save()
{
_entities.SaveChanges();
}
}
So i create a User repository that inherences from the above class as you can see here :
public class userRepository:GenericRepository<InModelContainer,User>
{
}
My problem is ,how can i call FindBy() method in my class ,My User entity is like this :
public partial class User
{
public User()
{
this.Ideas = new HashSet<Idea>();
this.Companies = new HashSet<Company>();
}
public int Id { get; set; }
[DisplayName("نام")]
[Required(ErrorMessage = "نام را وارد کنید")]
public string Name { get; set; }
}
I need to find a User By id,so i have to use findBy method but i don't know how can i call this method .
Example:
userRepository objRepository= new userRepository();
public ActionResult Edit(int id)
{
return View(objRepository.FindBy());
}
What should i pass to the above function ?
Best regards.
I am using MVC4 and EF6.
here you go
userRepository objRepository= new userRepository();
public ActionResult Edit(int id)
{
return View(objRepository.FindBy(user => user.Id == id).FirstOrDefault());
}
this will filter users based on the id and will take the first one or null if there is no match. You can choose to use .First() also if you want an exception instead.

Reading entity properties in generic repository

I'm writing a simple logging mechanism for my app.
I have generic repository:
public class GenericRepository<TEntity>:IRepository<TEntity> where TEntity : class
{
internal Equipment_TestEntities context;
internal DbSet<TEntity> dbSet;
internal Log entry;
public GenericRepository(Equipment_TestEntities context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
this entry= new Log();
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
AddLog("insert "+typeof(TEntity)+" "+entity.ToString());
}
private void AddLog(string action)
{
entry.Action = action;
entry.Date = DateTime.Now;
string username = HttpContext.Current.User.Identity.Name;
username = username.Substring(username.LastIndexOf("\\") + 1);
entry.Who = 1;
context.Logs.Add(entry);
}
}
In entry.Action I want to keep:
Action eg. Insert
Which entityUsed eg. User or Role
Something to identify entity
In 1) I can easily hardcone action
2) I can use TypeOf and get entity class name
But in 3rd I have a bit problem.
In case of insert I can ask db for the newest record but what should I do in Edit/remove cases?
Is there any ways to get properties value from those entities?
#Update:
sample part from unitOfWork:
public IRepository<Storage> storageRepository
{
get
{
if (this.StorageRepository == null)
{
this.StorageRepository = new GenericRepository<Storage>(context);
}
return StorageRepository;
}
}
IUnitOfWork:
public interface IUnitOfWork : IDisposable
{
IRepository storageRepository { get; }
}
I'd create an interface for the entities:
public interface IEntity
{
int? Id { get; set; }
}
Then change the generic constraint:
public class GenericRepository<TEntity>:IRepository<TEntity>
where TEntity : class, IEntity
{
...
}
Now you can simply use entity.Id to identify your entities.:
public virtual void Remove(TEntity entity)
{
if (!entity.Id.HasValue) {
throw new Exception("Cannot remove " + entity + ", it has no ID");
}
...
}

implement generic repository in ASP.NET MCV5

i am using ASP.NET mvc 5 in visual studio 2013. I have i process to implement generic repository and later on UnitOfWork. I have IGenericRepository which has IQueryable one function, because i want to learn and understand so i kept simple as possible. I have GenericRepository class where i am implementing this interface. I got FunctionContext which is inherited from baseContext. The reason i have baseContext so all the dbcontexts can use one path to hit database but same time keep number of table limited to business need.
I got error coming in GenericRepository class under GetAll function, i believe i am not extracting data properly.
many thanks in advanced....
IGernericRepository
public interface IGenericRepository<TEntity> : IDisposable
{
IQueryable<TEntity> GetAll { get; }
}
GenericRepository
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
private FunctionsContext _Context = new FunctionsContext();
public GenericRepository()
{
}
public IQueryable<TEntity> GetAll()
{
/* return _Context.Functions.Select(x => new Functions
{
Function_ID = x.Function_ID,
Title = x.Title,
Hierarchy_level = x.Hierarchy_level
});*/
????????????????????? need help here!
}
public void Dispose()
{
}
}
FunctionsContext
public class FunctionsContext : BaseContext<FunctionsContext>
{
public DbSet<App_Functions> Functions { get; set; }
}
BaseContext
public class BaseContext<TContext> : DbContext where TContext : DbContext
{
static BaseContext()
{
Database.SetInitializer<TContext>(null);
}
protected BaseContext()
: base("name = ApplicationDbConnection")
{ }
}
Functions Table (model)
[Table("Functions")]
public class App_Functions
{
public App_Functions()
{
// this.App_Controllers = new List<App_Controllers>();
}
[Key]
public int Function_ID { get; set; }
[StringLength(50)]
[Required]
public string Title { get; set; }
public int Hierarchy_level { get; set; }
}
Controller class
using (var repository = new GenericRepository<Functions>())
{
foreach(var functions in repository.GetAll)
{
var a7 = functions.Title;
??????
}
}
DbSet<TEntity> implements IQueryable<> so you should be able to just do this:
public IQueryable<TEntity> GetAll()
{
return _Context.Functions;
}
To make it generic, working for all types of TEntity:
public IQueryable<TEntity> GetAll()
{
return _Context.Set<TEntity>();
}
Give it a try and let me know if it works for you.
I don't think the other answer really addresses the ?????? bit.
This does:
public IQueryable<TEntity> GetAll()
{
return _Context.Set<TEntity>();
}
Although, I wouldn't do it as a method. Do it as a read-only property.
public IQueryable<TEntity> Entities
{
get { return _Context.Set<TEntity>(); }
}
// Generic Repository
public class Repository<T> where T : class
{
private readonly DbSet<T> _dbSet;
public Repository(DbSet<T> dbSet)
{
_dbSet = dbSet;
}
public IEnumerable<T> Where(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where);
}
public T FirstOrDefault(Expression<Func<T, bool>> where)
{
return _dbSet.FirstOrDefault(where);
}
// other methods
}
// Unit of Work interface
public interface IUnitOfWork
{
Repository<Product> ProductsRepository { get; }
}
// Unit of Work implementation
public class MyContext : DbContext, IUnitOfWork
{
private readonly Repository<Product> _products = null;
public DbSet<Product> Products { get; set; }
public MyContext()
: base("MyContext")
{
_products = new Repository<Product>();
}
public Repository<Product> ProductsRepository
{
get { return _products; }
}
}

Generic access to DbContext

ObjectContext allows generic access to the generated Entities. DbContext appears to have no such support. Accessing EF5 with a generic repository is challenging. Let's say I want a generic mechanism to read any given entity, call it TEntity:
public class DataRepositoryEF5<T> where T: DbContext
{
private ObjectContext _context;
public DataRepositoryEF5(DbContext context)
{
_context = ((IObjectContextAdapter)context).ObjectContext;
}
public IEnumerable<TEntity> ReadAll<TEntity>() where TEntity : class,new()
{
return GetObjectSet<TEntity>().AsEnumerable();
}
protected ObjectSet<TEntity> GetObjectSet<TEntity>() where TEntity : class,new()
{
ObjectSet<TEntity> result;
result = _context.CreateObjectSet<TEntity>();
return result;
}
}
Usage
var context = new MyContext();
var repository = new DataRepositoryEF5<MyContext>(context);
IEnumerable<Document> results = repository.GetAll<Document>();
foreach (var item in results)
{
Console.WriteLine("{0} {1} {2} {3}", item.Description, item.Id, item.Property, item.Whatever);
}
EF used to generate classes with a common base type EntityObject. Since that is no longer the case the best constraint I can have is class...
Second, because there is no equivalent of ObjectContext.CreateObjectSet<>() I am forced to cast from DbSet to ObjectSet.
With this pattern in place I have no need for DbContext. Without generics I am forced to hand code all CRUD operations. Did I miss something? If not, is it possible to tell EF5 to generate code with ObjectContext instead?
have a look at this tip that I posted a while ago
Anyway the trick is by using context.Set<>
public interface IEntity
{
int Id { get; set; }
}
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity
{
private IDbContext _context;
public Repository(IDbContext context)
{
_context = context;
}
private IDbSet<TEntity> DbSet
{
get
{
return _context.Set<TEntity>();
}
}
public IQueryable<TEntity> GetAll()
{
return DbSet.AsQueryable();
}
public void Delete(TEntity entity)
{
DbSet.Remove(entity);
}
.....
This is a more up to date and complete answer.
using Library.Models;
using Library.EF;
namespace Abstractions
{
public interface IKeyedModel
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
}
public class GenericContext<T> : DbContext where T : class, IKeyedModel
{
public DbSet<T> Items { get; set; } = default!;
}
public interface IRepository<T> where T : class, IKeyedModel
{
public GenericContext<T> Context() => new GenericContext<T>();
public T Select(int id) => Context().Items.Single(x => x.Id == id);
public IQueryable<T> Select() => Context().Items;
public void Insert(T item)
{
var context = Context();
context.Items.Add(item);
context.SaveChanges();
}
public void Update(T item)
{
var context = Context();
context.Items.Attach(item);
context.SaveChanges();
}
public void Delete(int id)
{
var context = Context();
var item = context.Items.Single(x => x.Id == id);
context.Items.Remove(item);
context.SaveChanges();
}
}
}
namespace Models
{
[Table(name: "User")]
public class User : IKeyedModel
{
public int Id { get; set; }
public string Name { get; set; } = default!;
}
}
namespace App
{
public class UserRepository : IRepository<User> { /* empty */ }
}

Categories

Resources