Linq 2 Sql - How to design proper repository, controller and view-model flow with entity inheritance
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开发者_JS百科, 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.
This sounds pretty close to your question:
Repository pattern and inheritance in .net
I'm using Linq to Sql in an MVC app, and have some table inheritance to represent items on a "floor". I have a base "table", and 2 tables that link to the base table and then extend the base table adding their own columns.
For me, because my sub-tables don't deviate too much from the base table, I create a database view that returns all the base-table columns plus the key extra columns from the derived tables, and a "type" to identify what they are. My repository then works with this database view.
This might be useful for you as an approach, depending on how many sub-types you have, how they differ, and your requirements. Otherwise, @smartcaveman made a good suggestion.
精彩评论