I am trying to use the repository pattern for a site made in .Net 2.0. All client code is expecting datatable for binding and I am not going to be able to change that, so please bear with me.
I am having a (probably dumb) issue. I cannot figure out how to pass a strongly typed entity to my concrete repository. The interface is forcing me to pass an Employee type but I need to pass a Developer type (it derives from Employee) because it has specific properties not found in the base class.
public interface IEmployeesRepository
{
DataTable Employees { get; }
void SaveEmployee(Employee employee);
void DeleteEmployee(Employee employee);
}
public class DevelopersRepository : IEmployeesRepository
{
public void SaveEmployee(Developer employee)
{
Database db = new SqlDatabase(connectionString);
DbCommand dbCommand = db.GetStoredProcCommand("Developers_Insert", employee.ProgrammingLanguage);
db.ExecuteNonQuery(dbCommand);
}
}
}
I tried using generics instead but then I still will not have a strongly typed object right?
I could be wrong but it sounds like you want to use a generic constraint:
public interface IEmployeeRepository<T>
where T : Employee
{
DataTable Employees { get; }
void SaveEmployee(T employee);
void DeleteEmployee(T employee);
}
public class DevelopersRepository : IEmployeeRepository<Developer>
{
public void SaveEmployee(Developer employee)
{
Database db = new SqlDatabase(connectionString);
DbCommand dbCommand = db.GetStoredProcCommand("Developers_Insert", employee.ProgrammingLanguage);
db.ExecuteNonQuery(dbCommand);
}
}
DevelopersRepository implements IEmployeesRepository so it must implement all methods in the interface.
public void SaveEmployee(Employee employee)
{
if (!(employee is Developer)) throw new Exception("...");
...
}
Related
I am trying to design my application architecture using ado.net with sql server. I am consider to use threee layers as follows:
Presentation Layer -> Business Layer (BAL) -> Data access Layer (DAL)
Entities for sample objects like Employee, Department etc..
I am trying to use interfaces as a contracts for some of my classes. My current issue is that i see some of the methods are common between BAL and DAL objects like: Add, Remove, GetAll therefore i decided to create interfaces to implement such things however when using from BAL classes i need to have it like void Add(Employee) but in DAL void Add(string name); therefore i splitted almost same interfaces on DAL and BAL (i do not like it because it seems to be somehow duplicated). Next issue is when want to use my code at the StickTogether class i am not able to call for instance _employee.Department = _department; I know it's because Department property should be in RepositoryBal interface but then simple entity Department would need to implement such interface which i dont want to do because as far as i read entities are just simple repeesentation of specific object. Could you tell me - best show on example how you would create such architecture or modify my to have something better than what i have right now. Below find my full code i am working on. How this could be fixed?
Please note i also start to prepare this code for dependency which will be helpfull for moc tests.
Appreciate your answers with proposed fixed solution based on my code.
public class StickTogether
{
private readonly IRepositoryBal<Employee> _employee;
private readonly IRepositoryBal<Department> _department;
public StickTogether(IRepositoryBal<Employee> employee, IRepositoryBal<Department> department)
{
_employee = employee;
_department = department;
}
public void Create()
{
_employee.Add(new Employee());
_department.Add(new Department());
_employee.Department = _department; //not accessible which has a sense
}
}
public interface IEntity
{
int Id { get; set; }
}
public class Employee : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public Department Department { get; set; }
}
public class Department : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
public interface IRepositoryDal<T> where T : IEntity
{
void Add(string name);
void Delete(int id);
IEnumerable GetAll();
}
public interface IRepositoryBal<T> where T : IEntity
{
void Add(T entity);
void Delete(T entity);
IEnumerable<T> GetAll();
}
internal class DepartmentBal : IRepositoryBal<Department>
{
private readonly IRepositoryDal<Department> _departmentDal;
public DepartmentBal(IRepositoryDal<Department> department)
{
_departmentDal = department;
}
public void Add(Department entity)
{
_departmentDal.Add(entity.Name);
}
public void Delete(Department entity)
{
_departmentDal.Delete(entity.Id);
}
public IEnumerable<Department> GetAll()
{
return (IEnumerable<Department>)_departmentDal.GetAll();
}
}
public class DepartmentDal : IRepositoryDal<Department>
{
public void Add(string name)
{
//call sql server stored procedure to add department;
}
public void Delete(int id)
{
//call sql server stored procedure to delete department by id;
}
public IEnumerable GetAll()
{
//call sql server stored procedure to return all employees;
return null;
}
}
internal class EmployeeBal : IRepositoryBal<Employee>
{
private readonly IRepositoryDal<Employee> _employeeDal;
public EmployeeBal(IRepositoryDal<Employee> employee)
{
_employeeDal = employee;
}
public void Add(Employee entity)
{
_employeeDal.Add(entity.Name);
}
public void Delete(Employee entity)
{
_employeeDal.Delete(entity.Id);
}
public IEnumerable<Employee> GetAll()
{
return (IEnumerable<Employee>) _employeeDal.GetAll();
}
}
public class EmployeeDal : IRepositoryDal<Employee>
{
public void Add(string name)
{
//call sql server stored procedure to add employee;
}
public void Delete(int id)
{
//call sql server stored procedure to delete employee by id;
}
public IEnumerable GetAll()
{
//call sql server stored procedure to return all employee;
return null;
}
}
The 3 layer (anti pattern?) is a red herring here, you're essentially talking a dependency injection. pattern. These become difficult to manage manually. I'd suggest you implement a DI framework like Simple Injector or Unity.
I am trying to use interfaces as a contracts for some of my classes.
Why some of your classes? If your going to implement dependency injection then implement it on all classes.
My current issue is that i see some of the methods are common between
BAL and DAL objects like: Add, Remove, GetAll therefore i decided to
create interfaces to implement such thing
Here's your first mistake. You've decomposed based on functionality, not responsibility. Just because something has a similar method signature does not mean they should be related. A Customer business object has a very different responsibility to a Customer data object. Remember favour composition over inheritance.
however when using from BAL classes i need to have it like void
Add(Employee) but in DAL void Add(string name);
This just highlights the above, you've made the decision that because the methods are called "Add" their the same, their obviously not.
I would say you should implement an interface for each object, dont' try and relate unrelated object, then configure this using a DI framework, then inject them. Try not to blur your lines and keep your seperations clear. Remember you want high cohesion and low coupling.
To give some examples I'd forget about your IRepositoryBal and the generics altogether and just simplify the whole thing:
//your going to struggle to do DI with internal classes, make them public
public class EmployeeBal : IEmployeeBal
{
//
}
public interface IEmployeeBal
{
void Add(Employee entity);
void Delete(Employee entity);
IEnumerable<Employee> GetAll();
Department Department {get; set;}
}
public class StickTogether
{
private readonly IEmployeeBal _employee;
private readonly IDepartmentBal _department;
public StickTogether(IEmployeeBal employee, IDepartmentBal department)
{
_employee = employee;
_department = department;
}
public void Create()
{
_employee.Add(new Employee());
_department.Add(new Department());
_employee.Department = _department; //not accessible which has a sense
}
}
You then configure these in your DI framework, for example in simple Injector you would do:
Container _defaultContainer = new Container();
_defaultContainer.Register<IEmployeeBal, EmployeeBal>();
_defaultContainer.Register<IDepartmentBal, DepartmentBal>();
_defaultContainer.Register<IDepartmentDal, DepartmentDal>();
//..etc.
you then get your parent instance (only!) thus:
IEmployeeBal entryPoint = _defaultContainer.GetInstance<IEmployeeBal>();
the DI framework does the rest and all your dependencies are decoupled.
I can't figure out why I am getting the error cannot be used as type parameter 't' in the generic type or method...There is no implicit reference conversion from...
Here is my entire piece of code (simplified):
The problem is on the line RefreshLocalListFromLocalStore(TestDataObjectTable);
using System;
using Microsoft.WindowsAzure.MobileServices;
using Microsoft.WindowsAzure.MobileServices.SQLiteStore;
using Microsoft.WindowsAzure.MobileServices.Sync;
public class TestDataObject
{
#region Properties
public string Id { get; set; }
#endregion
}
public class TestDatabaseManager
{
public MobileServiceClient Client;
private IMobileServiceSyncTable<TestDataObject> TestDataObjectTable;
public TestDatabaseManager()
{
CurrentPlatform.Init();
Client = new MobileServiceClient("SomeUrl");
var store = new MobileServiceSQLiteStore("SomePath");
store.DefineTable<TestDataObject>();
TestDataObjectTable = Client.GetSyncTable<TestDataObject>();
RefreshLocalListFromLocalStore(TestDataObjectTable);
}
#region Methods
public async void RefreshLocalListFromLocalStore<T>(T table) where T : IMobileServiceSyncTable<T>
{
try
{
await table.ToListAsync();
}
catch (Exception e)
{
}
}
#endregion
}
Your generic constraint is probably wrong. Use the following declaration for RefreshLocalListFromLocalStore:
public async void RefreshLocalListFromLocalStore<T>(IMobileServiceSyncTavble<T> table)
In your declaration, the table should have been a table of tables, which does not make sense. You can use the generics constraints still to limit what kind of elements you want to have for your table, for example if the elements in the table should be entities complying with some IEntity interface.
public async void RefreshLocalListFromLocalStore<T>(IMobileServiceSyncTavble<T> table) where T : IEntity
The problem is you're using T with constraint of Type IMobileServiceSyncTable<T> where T is again of Type IMobileServiceSyncTable<T>.
Use constraints on the type for generic interface
public async void RefreshLocalListFromLocalStore<T>(IMobileServiceSyncTable<T> table)
where T : TestDataObject
{
}
See specification of using Type constraints.
T is IMobileServiceSyncTable<TestDataObject>
T must implement IMobileServiceSyncTable<T>
but it doesn't, because that would be
IMobileServiceSyncTable<IMobileServiceSyncTable<TestDataObject>>
Try this instead:
public async void RefreshLocalListFromLocalStore<T>(IMobileServiceSyncTable<T> table)
{
...
}
i have this existing code
public interface IRepository<T>
{
void Create(T obj);
T Retrieve(string key);
}
public class ItemRepository : IRepository<Item>
{
public void Create(Item obj)
{
//codes
}
public Item Retrieve(string key)
{
//codes
}
}
i would like to create a General class repository where i have to inject a type of IRepository to the constructor then use its own implementation of the methods. i already have an existing code but it is currently wrong
public class Repository
{
IRepository<T> action = null;
public Repository(IRepository<T> concreteImplementation)
{
this.action = concreteImplementation;
}
public void Create(T obj)
{
action.Create(obj);
}
}
the classes are from EF. if there is no work around for this what will be the best approach?
If I understand you correctly you want a single repository which can create or retrieve an object of any type by delegating to a type specific repository implementation?
How do you imagine this working? you defined this Repository class, but you have to create a concrete implementation of the actual repository in order to use it, and then still have to create an instance of Repository anyway. Why not just use the generic implementation you have to create anyway?
And what about your Retrieve method? How will this look in your Repository class? Will you just return Object? or will you make your method generic?
Anyway to answer your question, you could do this I suppose:
public class Repository
{
IRepository action = null;
public Repository(IRepository concreteImplementation)
{
this.action = concreteImplementation;
}
public void Create<T>(T obj)
{
action.Create(obj);
}
}
but you have to introduce a non generic interface as well, as you can't require an interface with a generic parameter in the constructor without specifying the generic type on the class.
public interface IRepository
{
void Create(object obj);
object Retrieve(string key);
}
Or possibly you could pass in the type into the Create method instead of having a generic parameter:
public class Repository
{
IRepository action = null;
public Repository(IRepository concreteImplementation, Type respositoryType)
{
this.action = concreteImplementation;
expectedType=repositoryType;
}
public void Create(Type type, Object obj)
{
if(type==expected && obj.GetType()==type)
{
action.Create(obj);
}
}
}
but both of these are terrible ideas. Just use the generics and create a repository per type, it'll be best in the long run
I think you might just be missing the definition of T in the context of the general repository class.
Try adding <T> to the it like this:
public class Repository<T>
{
...
}
I'm working on a repository for a list of entities, and I should repeat thea same class more than once, the only difference is type type .. is there a way to make it generic?
It should quite easy, for sure I don't know how to make this generic:
private Namespace.DAL.UserProfileRepository _rep = new Namespace.DAL.UserProfileRepository();
The class I'm repeating it this:
public class UserProfileRepository : IEntityRepository<IUserProfile>
{
private Namespace.DAL.UserProfileRepository _rep = new Namespace.DAL.UserProfileRepository();
public IUserProfile[] GetAll()
{
return _rep.GetAll();
}
public IUserProfile GetById(int id)
{
return _rep.GetById(id);
}
public IQueryable<IUserProfile> Query(Expression<Func<IUserProfile, bool>> filter)
{
return _rep.Query(filter);
}
}
#NickBray hit the nail on the head. Regardless of how different or similar the actual concrete repository implementations are the DAL class in your example should expose the repository instance via an interface.
Ideally the exposed interface would be declared something like this.
interface IUserProfileRepository : IEntityRepository<IUserProfile>
{
}
This way you could add custom IUserProfile methods as necessary. While the IEntityRepository interface would define the common methods Add, Update, Remove and various QueryXXX methods.
I hope this example helpful for you. If I correctly understood your question, you want to make generizable your repository based on the interface "IEntityRepository".
Try something like this:
public class UserProfileRepository<TUserProfile> : IEntityRepository<TUserProfile> where TUserProfile : IUserProfile
{
private Namespace.DAL.UserProfileRepository _rep = new Namespace.DAL.UserProfileRepository();
public TUserProfile[] GetAll()
{
return _rep.GetAll();
}
public TUserProfile GetById(int id)
{
return _rep.GetById(id);
}
public IQueryable<TUserProfile> Query(Expression<Func<TUserProfile, bool>> filter)
{
return _rep.Query(filter);
}
}
i am pretty new to the repository design pattern and i have reached a dead end while trying to implement it, with regards to inheritance.
I am not sure even if i started in the right direction.
So basically i will have an abstract base class Product, with id and imagePath for instance, and will have several products which inherit from this.
namespace Common
{
public abstract class Product
{
public int Id { get; set; }
public string ImgPath { get; set; }
}
public class Scale : Product
{
public int AdditionalProperty { get; set; }
}
}
Now the repositories are as follows:
public class BaseRepository
{
protected TEstEntities1 _dataContext = new TEstEntities1();
public BaseRepository()
{
_dataContext = new TEstEntities1();
}
}
public interface IProductRepository
{
Common.Product Get(int id);
void Add(Common.Product p);
void Update(Common.Product p);
List<Common.Product> ListAll();
}
public class ProductRepository : BaseRepository, IProductRepository
{
public Common.Product Get(int id)
{
throw new NotImplementedException();
}
public void Add(Common.Product p)
{
throw new NotImplementedException();
}
public void Update(Common.Product p)
{
throw new NotImplementedException();
}
public List<Common.Product> ListAll()
{
throw new NotImplementedException();
}
}
My problem is as follows: how do i integrate operations regarding Scale ? It seems a bad idea to add something like Add(Common.Scale s) to the IProductRepository. It seems like a bad idea to see inside the Add(Common.Product p) which type of Product i try to add, then cast to it, then add.
I guess that if i were to describe this problem more thoroughly, I want to repeat as few code as possible, to somehow isolate base product adding/removing code in the product repository, and somehow put e.g. Scale specific code for adding/removing inside another class, or method.
A more thorough approach of mine has been this one:
public interface IProductRepository<T> where T : Common.Product
{
T Get(int id);
void Add(T p);
void Delete(T p);
}
public abstract class ProductRepository : BaseRepository
{
protected void Add(Common.Product p)
{
_dataContext.AddToProduct(new Product { Id = p.Id, Image = p.ImgPath });
_dataContext.AcceptAllChanges();
}
protected void Delete(Common.Product p)
{
var c = _dataContext.Product.Where(x => x.Id == p.Id).FirstOrDefault();
_dataContext.DeleteObject(c);
_dataContext.AcceptAllChanges();
}
protected Product Get(int id)
{
return _dataContext.Product.Where(x => x.Id == id).FirstOrDefault();
}
}
public class CantarRepository : ProductRepository, IProductRepository<Common.Scale>
{
public void Add(Common.Scale p)
{
base.Add(p);
_dataContext.Scale.AddObject
(new Scale { ProductId = p.Id, AdditionalProperty = p.AdditionalProperty });
_dataContext.AcceptAllChanges();
}
public void Delete(Common.Scale p)
{
var c = _dataContext.Scale.Where(x => x.ProductId == p.Id);
_dataContext.DeleteObject(c);
_dataContext.AcceptAllChanges();
base.Delete(p);
}
public new Common.Scale Get(int id)
{
var p = base.Get(id);
return new Common.Scale
{
Id = p.Id,
ImgPath = p.Image,
AdditionalProperty = _dataContext.Scale.Where
(c => c.ProductId == id).FirstOrDefault().AdditionalProperty
};
}
}
Unfortunatelly this falls short for one reason.
If i use a factory pattern to return an IProductRepository and inside it i instantiate with IProductRepository this will not work because of covariance and contravariance, and IProductRepository can't be contravariant and covariant at the same time, and splitting the methods into two interfaces seems counterintuitive and cumbersome.
I suspect i will need the factory pattern in order to have a base class interface returned, but i am open to suggestions on this as well. As i've said, i am very newbie regarding the repo pattern.
I am curious as to what i am doing wrong, how i can solve this, and how can i implement this better.
Thanks.
You are using inheritance incorrectly. You cannot treat Scale as a (is-a) Product if the important difference is additional properties - that makes the exposed interface of Scale different than Product, and at that point inheritance simply gets in your way. Use inheritance to share behavior, not properties.
What problem are you trying to solve with your use of inheritance?
I want to repeat as few code as
possible
Wouldn't it be better to have a little duplication in order to get things done, rather than spin your wheels trying to work with an implausible design?
Also, this is all you are sharing with your inheritance:
public int Id { get; set; }
public string ImgPath { get; set; }
Repeating the definition of two auto-implemented properties almost doesn't even qualify as duplication, it most certainly is not an issue to be concerned about.
Misusing inheritance, however, is fairly grievous. The next person to maintain your app will curse you for it.
So basically i will have an abstract
base class Product, with id and
imagePath for instance, and will have
several products which inherit from
this.
So when you add new types of products you will have to extend an inheritance hierarchy? That seems like a bad idea.
I'm not a big fan of generic repository but after looking at your code I think you should use it:
public interface IEntity
{
int Id { get; }
}
public interface IRepository<T> where T : class, IEntity
{
IQueryable<T> GetQuery();
T Get(int id);
void Add(T entity);
void Update(T entity);
void Delete(T entity);
}
implementation:
public Repository<T> where T : class, IEntity
{
private ObjectSet<T> _set; // or DbSet
private ObjectContext _context; // or DbContext
public Repository(ObjectContext context) // or DbContext
{
_context = context;
_set = context.CreateObjectSet<T>(); // _context.Set<T>() for DbContext
}
public IQueryable<T> GetQuery()
{
return _set;
}
public T Get(int id)
{
return _set.SingleOrDefault(e => e.Id == id);
}
public void Add (T entity)
{
_set.AddObject(entity);
}
public void Update(T entity)
{
_set.Attach(entity);
context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
// or context.Entry(entity).State = EntityState.Modified; for DbContext
}
public void Delete(entity)
{
_set.Attach(entity);
_set.DeleteObject(entity);
}
}
There is NO AcceptAllChanges because it will reset ObjectStateManager and your changes will never be saved. There is no recreation of objects because it doesn't make sense.
Using this repository is as simple as:
var repo = new BaseRepository<Product>(context);
repo.Add(new Product() { ... });
repo.Add(new Scale() { ... }); // yes this works because derived entities are handled by the same set
context.Save();
I recently implemented something like this. (Using your sample types names) I have a single ProductRepository which knows how to persist/unpersist all Product subtypes.
Ultimately, your backing data store will have to have the ability to store the various subtypes and any properties which they introduce. Your repository type will also have to know how to take advantage of those features for each given subtype. Therefore, each time you add a subtype, you will have work involved in, for example, adding table columns to your backing data store to hold properties it may introduce. This implies that you will also need to make the appropriate changes to your repository type. It seems easiest, therefore, to examine the type of the entity when passed to your repository type and throw an exception if it is not a supported type since there's nothing else your repository will be able to do with it. Similarly, when retrieving the list of entities, the repository will have to know how to retrieve each entity subtype and construct an instance. Since these all derive from Product, they can all form items an in IEnumerable<Product> return value.