[英]How to implement Repository Pattern with interface, base and concrete
I have almost completed implementing my repository pattern by having a IRepository<T>
interface, a NewsRepository
class and a News
entity. 我几乎已经通过具有
IRepository<T>
接口, NewsRepository
类和News
实体来实现我的存储库模式。 The problem I ran into was trying to abstract out common methods to a base Repository class. 我遇到的问题是试图将通用方法抽象为基本的Repository类。
I could not find a way to abstract the Get method in the NewsRepository
as it contains a specific Linq expression. 我找不到在
NewsRepository
抽象Get方法的方法,因为它包含特定的Linq表达式。
My questions are : 我的问题是 :
1) How do I abstract to a base class the public T Get(int id)
method please? 1)如何将
public T Get(int id)
方法抽象到基类? The only way I have done it so far is by passing in Expression<Func<T,bool>>
instead of an int, but then that deosn't really abstract out common behaviour as each sub-class will still need to pass in an expression that is almost identical in each case ie n => n.id == id
. 到目前为止,我这样做的唯一方法是传入
Expression<Func<T,bool>>
而不是int,但是这样就不会真正抽象出常见的行为,因为每个子类仍需要传入一个在每种情况下都几乎相同的表达式,即n => n.id == id
。
2) How do I pass into the base class on the Update method the sub-class GetViolations and map methods please? 2)如何将Update类的子类GetViolations和map方法传入基类? I imagine the solution is possibly by using delegates, but I couldn't get the syntax to compile
我想解决方案可能是通过使用委托,但是我无法获取语法进行编译
This is a simplified set of the code - in practice I have a Save method which does Update and Insert rather than just the Update shown here. 这是一组简化的代码-实际上,我有一个Save方法,它执行Update和Insert,而不仅仅是此处显示的Update。
public interface IRepository<T>
{
T Get(int id);
void Update(T item);
}
public class NewsRepository : IRepository<News>
{
private Table<News> _newsTable;
public NewsRepository(string connectionString)
{
_newsTable = new DataContext(connectionString).GetTable<News>();
}
public News Get(int id)
{
return _newsTable.SingleOrDefault(n => n.NewsId == id);
}
public void Update(News item)
{
var errors = item.GetRuleViolations();
if (errors.Count > 0)
throw new RuleException(errors);
News dbNews = _newsTable.SingleOrDefault(n => n.NewsId == item.NewsId);
map(dbNews, item);
_newsTable.Context.SubmitChanges();
}
private void map(News dbNews, News news)
{
dbNews.Title = news.Title;
dbNews.Article = news.Article;
}
}
public class Repository<T> where T : class
{
protected Table<T> _table;
public Repository(Table<T> t)
{
_table = t;
}
//How do i do this??! - This doesn't compile due to T no having a NewsId
public T Get(int id)
{
return _table.SingleOrDefault(n => n.NewsId == id);
}
//This seems to be a solution, but it's not really abstracting common behaviour as each
//sub-class will still need to pass in the same linq expression...
public T Get(Expression<Func<T,bool>> ex)
{
return _table.SingleOrDefault(ex);
}
public void Update(T item)
{
//How is it possible to pass in the GetRuleViolations and map functions to this method?
var errors = item.GetRuleViolations();
if (errors.Count > 0)
throw new RuleException(errors);
T dbNews = _table.SingleOrDefault(n => n.NewsId == item.NewsId);
map(dbNews, item);
_table.Context.SubmitChanges();
}
}
Here is an example: 这是一个例子:
public interface IEntity
{
int Id { get; }
}
public partial class News : IEntity
{
}
public class Repository<T> where T : class, IEntity
{
private readonly DataContext _db;
public Repository(DataContext db)
{
_db = db;
}
public T Get(int id)
{
Expression<Func<T, bool>> hasId = HasId(id);
return _db.GetTable<T>().Single(hasId);
}
// entity => entity.Id == id;
private Expression<Func<T, bool>> HasId(int id)
{
ParameterExpression entityParameter = Expression.Parameter(typeof (T), "entity");
return Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(entityParameter, "Id"),
Expression.Constant(id)
),
new[] {entityParameter}
);
}
}
See also http://msdn.microsoft.com/en-us/library/bb397951.aspx 另请参阅http://msdn.microsoft.com/en-us/library/bb397951.aspx
It really helps to have a layer supertype for entities . 为实体提供层超类型确实有帮助。 They will share an Id property.
他们将共享一个ID属性。 You won't have to deal with an expression to represent the id proeprty, you'll just know what it is.
您无需处理表示id属性的表达式,您只需知道它是什么即可。
The template method pattern . 模板方法模式 。 In this pattern your base Update does all the work calling helper methods in order, and your derived classes implement those protected abstract helper methods.
在这种模式下,基础Update会按顺序执行所有工作,调用辅助方法,而派生类将实现那些受保护的抽象辅助方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.