Question: I'm wondering what type of Repository and Controller design/work-flow people implement when using entity inheritance in a ORM, in this case LINQ 2 SQL with MVC .NET.
I have a very simple hierarchy where a Clothing class (concrete) inherits from Product (abstract class). However, this complicates the design quite a bit. It would be foolish to make a repository class per concrete implementation of Product, so I use Product as a parameter type and return type in my 'Product' repository. "However, because of this I must cast the Product type to a concrete implementation of Product (either before requesting from the repository or after).
Another thing I noticed is that even if I determine the correct type to cast to, I have to define my view-models to pass to my view for each concrete implementation of Product.
If this is what needs to be done, so be it, but I'm interested what other people's thoughts and/or experience are.
For the sake of this discussion, let's assume your repository interface looks something like:
public interface IRepository<T>{
T GetById(int id);
IQueryable<T> All();
void Add(T entity);
void Remove(T entity);
}
And while you are correct that implementing a repository for each Product
type is unnecessary, you could create a generic wrapper class that implements the interface as if it were a dedicated repository. For example,
public class RepositoryWrapper<T,TBase> : IRepository<T> {
where T: TBase
private readonly IRepository<TBase> _repository;
public RepositoryWrapper(IRepository<TBase> repository){
_repository = repository;
}
public T GetById(int id){
return (T)_repository.GetById(id);
}
public IQueryable<T> All(){
return _repository.All().OfType<T>();
}
public void Add(T entity){
_repository.Add(entity);
}
public void Remove(T entity){
_repository.Remove(entity);
}
}
Your use case would be a RepositoryWrapper<Clothing,Product>
, and you could simplify the creation via an extension method, such as:
public static class SubRepositories{
public static IRepository<TDerived> GetSubClassRepository<TBase,TDerived>(this IRepository<TBase> repository)
where TDerived: TBase
{
return new RepositoryWrapper<TDerived,TBase>(repository);
}
}
Now, as far as the view model concern, you don't need to specify the exact type of the view model when passing it in your controller. An alternative is to use templates to automatically determine the type of view to render based on the ModelMetadata.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With