I am new to ASP.NET and very new to EF. I am trying to develop an application and after reading some sites I've decided I'm going to create a 3-tier application (DAL, BL, a website as the frontend).
For the DAL layer I've taken inspiration from here
http://codefizzle.wordpress.com/2012/07/26/correct-use-of-repository-and-unit-of-work-patterns-in-asp-net-mvc/
public interface IGenericRepository<T> where T : class
{
void Add(T a);
}
public interface IUnitOfWork:IDisposable
{
IGenericRepository<UserInfo> UserInfoRepository { get; }
void Commit();
}
public class EfGenericRepository<T> : IGenericRepository<T> where T : class
{
private DbSet<T> _dbSet;
public EfGenericRepository(DbSet<T> dbSet)
{
_dbSet = dbSet;
}
public void Add(T a)
{
_dbSet.Add(a);
}
}
public class EfUnitOfWork : DbContext, IUnitOfWork
{
private readonly EfGenericRepository<UserInfo> _userInfoRepo;
public DbSet<UserInfo> UserInfos { get; set; }
public EfUnitOfWork()
{
_userInfoRepo = new EfGenericRepository<UserInfo>(UserInfos);
}
public IGenericRepository<UserInfo> UserInfoRepository
{
get { return _userInfoRepo; }
}
public void Commit()
{
this.SaveChanges();
}
}
and my BL looks like this:
public interface IBussinessLogic
{
void AddUserInfo(string c);
}
public class BusinessLogic: IBussinessLogic
{
private IUnitOfWork _unitOfWork;
public BusinessLogic()
{
_unitOfWork = new EfUnitOfWork();
}
public void AddUserInfo(string c)
{
_unitOfWork.UserInfoRepository.Add(new UserInfo()
{
Address = c
});
_unitOfWork.Commit();
}
}
Now I am using web-forms but I don't think that should be an issue.
On click i execute this:
IBussinessLogic businessLogic = new BusinessLogic();
businessLogic.AddUserInfo(address.Text);
But nothing happens,my data is not saved in the db.
Can anyone please help me?
Related
I am trying to use Dependency Injection for DB context. I am not sure what i am doing wrong but even after following all the steps i still get the error
Below are the steps that i follow ,suggest me where its going wrong. I am using multi tier project hence my repositories are in my DB access layer and controller in a mvc api application
My DB Context class
public partial class TestDbContext: DbContext
{
public TestDbContext(DbContextOptions<TestDbContext> options)
: base(options)
{
}
public virtual DbSet<Table1> Table1{ get; set; }
}
public interface IRepository<T> where T : class
{
IQueryable<T> GetDbSet();
}
public class Repository<T> : IRepository<T> where T : class
{
protected DbContext _entities;
protected readonly DbSet<T> _dbset;
public Repository(DbContext context)
{
_entities = context;
_dbset = context.Set<T>();
}
public virtual IQueryable<T> GetDbSet()
{
return _dbset;
}
}
pulbic interface IUserRepository
{
List<UsersInfo> GetUsers();
}
public class UserRepository:IUserRepository
{
private readonly IRepository<Table1> table1repo;
public UserRepository(IRepository<Table1> _table1Repo)
{
table1repo = _table1Repo;
}
public List<UsersInfo> GetUsers()
{
return table1repo.GetDbSet().ToList();
}
}
public class MyController : : ControllerBase
{
private readonly IUserRepository _UserRepo;
public MyController (IUserRepository UserRepo)
{
_UserRepo= clientInfo;
}
[HttpGet]
public async Task<IActionResult> Get()
{
try
{
var result = _UserRepo.GetUsers();
return new JsonResult(result) { SerializerSettings = new JsonSerializerSettings() { Formatting = Formatting.Indented } };
}
catch(Exception e)
{
throw e;
}
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
services.Configure<IISOptions>(options =>
{
options.AutomaticAuthentication = false;
});
services.AddDbContext<TestDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("ConnectionString")));
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
Your context type in your repository class should be TestDbContext instead of DbContext.
public class Repository<T> : IRepository<T> where T : class
{
protected TestDbContext _entities;
protected readonly DbSet<T> _dbset;
public Repository(TestDbContext context)
{
_entities = context;
_dbset = context.Set<T>();
}
public virtual IQueryable<T> GetDbSet()
{
return _dbset;
}
}
I have try to save data from database using Unit OF Work Pattern.But I got error.My code is:
Unit of Work code:
private PousadaManagementContext MinhaPousadaContext { get; }
public IPousadaRepository PousadaRepository { get; private set; }
public UnitOfWork
(
PousadaManagementContext minhaPousadaContext,
IPousadaRepository pousadaRepository
)
{
this.MinhaPousadaContext = minhaPousadaContext;
PousadaRepository = pousadaRepository;
}
public async Task<int> CompleteAsync()
{
return await MinhaPousadaContext.SaveChangesAsync();
}
public int Complete()
{
return MinhaPousadaContext.SaveChanges();
}
public void Dispose() => MinhaPousadaContext.Dispose();
public interface IUnitOfWork : IDisposable
{
int Complete();
Task<int> CompleteAsync ();
}
businessclass:
private UnitOfWork managementUoW { get; }
public PousadaBusiness(IUnitOfWork ManagementUoW)
{
ManagementUoW = managementUoW;
}
public async Task<Pousada> Save(Pousada p)
{
return await managementUoW.PousadaRepository.Save(p);
}
Here In Save method p all properties have value but managementUoW is null.
How to Solve this error.
I am about to start a small/medium sized project. I am by no means a software architect. But i tend to question every move i make at times. Since i want to do things correct.
I found a way to implement a simple repository, and i wanted to know if this is a "correct" way of doing it. I came to this solution, since i know what is going on, and not taking in something to complex before i have the knowledge :)
Here it goes.
Unit of work
Where i make sure i to keep all my repositories under the same dbcontext. In my uof i can access all repo's when calling it from the controller.
public class UnitOfWork : IDisposable
{
private ContactRepository _contactRepo;
private ApplicationDbContext _entities;
public UnitOfWork(ApplicationDbContext entities)
{
_entities = entities;
}
public ContactRepository ContactRepo
{
get
{
if (_contactRepo == null)
{
_contactRepo = new ContactRepository(_entities);
}
return _contactRepo;
}
}
public void Save()
{
_entities.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_entities.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
ContactRepository
This is a short example of a repository, where it recieves the dbcontext and uses it to grab whatever data i want
public class ContactRepository
{
private ApplicationDbContext _entities;
public ContactRepository(ApplicationDbContext entities)
{
_entities = entities;
}
public IEnumerable<Contact> GetAll()
{
return _entities.Contacts;
}
}
Controller
Short example of controller
public class ContactController : Controller
{
UnitOfWork uow = new UnitOfWork(new ApplicationDbContext());
public ActionResult Index()
{
var contacts = uow.ContactRepo.GetAll();
return View(contacts);
}
protected override void Dispose(bool disposing)
{
uow.Dispose();
base.Dispose(disposing);
}
}
In this way i will have access to all my repositories under the same dbcontext which i was aiming for.
I know things can be done smarter/different. With for example a extendable generic repo. But in this case i am aiming for something simple and understandable. But still dont want to make a huge mistake, if there is a major flaw.
Do you see any major flaws with this way of handling data trough entity framework?
If you're aiming for something simple then just use Entity Framework but if you're going to use the repository pattern I would encourage you to do it properly.
Two of the biggest motivators for using repository are:
You want to simplify CRUD applications to your database.This is
done through the use of interfaces and generics
You want to the ability to test the business logic in isolation
from external dependencies.Again, this is done through the use of
interfaces
Below will take you two minutes to implement but then at least you know you're doing it right, because at the moment you're trying to implement a great pattern in an ineffective way.
Generic interface:
public interface IRepository<T>
{
T GetById(int id);
IEnumerable<T> List();
IEnumerable<T> List(Expression<Func<T, bool>> predicate);
void Add(T entity);
void Delete(T entity);
void Update(T entity);
}
Generic repository:
public abstract class EntityBase
{
}
public class DBRepository<T> : IRepository<T> where T : EntityBase
{
private readonly DbContext _dbContext;
public DBRepository(DbContext dbContext)
{
_dbContext = dbContext;
}
public virtual T GetById(int id)
{
return _dbContext.Set<T>().Find(id);
}
public virtual IEnumerable<T> List()
{
return _dbContext.Set<T>().AsEnumerable();
}
public virtual IEnumerable<T> List(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
return _dbContext.Set<T>()
.Where(predicate)
.AsEnumerable();
}
public void Add(T entity)
{
_dbContext.Set<T>().Add(entity);
}
public void Update(T entity)
{
_dbContext.Entry(entity).State = EntityState.Modified;
}
public void Delete(T entity)
{
_dbContext.Set<T>().Remove(entity);
}
Unit of work:
public class UnitOfWork : IDisposable
{
private bool disposed = false;
private ApplicationDbContext context = new ApplicationDbContext();
private IRepository<Contact> _contactRepository;
public IRepository<Contact> ContactRepository
{
get
{
if (this._contactRepository == null)
this._contactRepository = new DBRepository<Contact>(context);
return _contactRepository;
}
}
public void Save()
{
context.SaveChanges();
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
context.Dispose();
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
im trying to implement a uniTest for my application so when i tried to get User by ID value in my application it's work fine, but when i tried to do the same scenario from my unit test class i always get nullable result even if the ID value is correct :
Class AccountController : ApiController
{
private UserService _UserService = null;
public AccountController()
{
_UserService = new UserService();
}
[AllowAnonymous]
[Route("test")]
public IHttpActionResult test()
{
var user = _UserService.getUserById(1); //user --> not null;
}
}
but when i tried a UnitTest Script
[TestClass]
public class userServiceTest
{
private UserService _UserService = null;
public userServiceTest()
{
_UserService = new UserService();
}
[TestMethod]
public void checkUserCase1()
{
var user = _UserService.getUserById(1); //user is null value !!!;
}
}
User Service :
public class UserService
{
private GenericRepository<User> _UserRepository = null;
public UserService()
{
_UserRepository = new GenericRepository<User>();
}
public User getUserById(int id)
{
return _UserRepository.Find(x => x.Id == id).FirstOrDefault();
}
}
The Generic Repository
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private MyDbContext db = null;
private DbSet<T> table = null;
public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
{
return table.Where(predicate);
}
}
IGeneric :
public interface IGenericRepository<T> where T : class
{
IEnumerable<T> SelectAll();
T SelectByID(object id);
void Insert(T obj);
void Update(T obj);
void Delete(object id);
void Save();
IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
}
My DB Context :
public class MyDbContext : DbContext
{
public MyDbContext()
: base("AuthWebApiDb")
{
Database.SetInitializer<MyDbContext>(new MyDbInitializer());
}
public DbSet<User> Users { get; set; }
}
I have Two Project : One is the simple project, the second is the Unit Test
Check if EF is innstalled in your UnitTest project.
Put the connection string in the app.config file in the unitest project.
Thank's #Stewart_T
I want to update a log file(txt) everytime when methods in a an interface class are called?
Is there any way to do this other than writing code in every method to create log?
Here's my 30 mins. you'll have to implement the logging code somewhere so you have to create another abstraction for your code. thus an abstract class is needed. i think. this is very quick and dirty.
public interface IService<T>
{
List<T> GetAll();
bool Add(T obj);
}
then you'll need the abstract class where you'll need to implement your logging routine
public abstract class Service<T> : IService<T>
{
private void log()
{
/// TODO : do log routine here
}
public bool Add(T obj)
{
try
{
log();
return AddWithLogging(obj);
}
finally
{
log();
}
}
public List<T> GetAll()
{
try
{
log();
return GetAllWithLog();
}
finally
{
log();
}
}
protected abstract List<T> GetAllWithLog();
protected abstract bool AddWithLogging(T obj);
}
as for your concrete classes
public class EmployeeService : Service<Employee>
{
protected override List<Employee> GetAllWithLog()
{
return new List<Employee>() { new Employee() { Id = 0, Name = "test" } };
}
protected override bool AddWithLogging(Employee obj)
{
/// TODO : do add logic here
return true;
}
}
public class CompanyService : Service<Company>
{
protected override List<Company> GetAllWithLog()
{
return new List<Company>() { new Company() { Id = 0, Name = "test" } };
}
protected override bool AddWithLogging(Company obj)
{
/// TODO : do add logic here
return true;
}
}
public class Employee
{
public int Id {get;set;}
public string Name { get; set;}
}
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
}
then on your implementation you can just..
static void Main(string[] args)
{
IService<Employee> employee = new EmployeeService();
List<Employee> employees = employee.GetAll();
foreach (var item in employees)
{
Console.WriteLine(item.Name);
}
IService<Company> company = new CompanyService();
List<Company> companies = company.GetAll();
foreach (var item in companies)
{
Console.WriteLine(item.Name);
}
Console.ReadLine();
}
hope this helps!
I think you would have to use Aspect Oriented Programming to achieve that. Read http://www.sharpcrafters.com/aop.net
I think you meant class (instead of interface)
Two options I can think of:
Implementing INotifyPropertyChanged which is in lines of writing code in every method
or
to adopt on of the AOP frameworks in the article http://www.codeproject.com/KB/cs/AOP_Frameworks_Rating.aspx if that is not a major leap