我正在使用ASP.NET MVC和洋葱架构创建一个Intranet网站。我一直在实现存储库模式,但我遇到了困难。
假设我有一个带有IDDocument的Document表。那么这是我的回购(只有一种方法):
class Repository<T> : IRepository<T> where T : class
{
private readonly PrincipalServerContext context;
private DbSet<T> entities;
//Constructor and stuff here
public T Get(long id)
{
return entities.SingleOrDefault(s => s.IDDocument == id);//Here is my problem
}
}
问题是我不能使用它,因为T不被识别为来自Document表。解决方案是创建一个BaseEntity:
public class BaseEntity{
public int ID{get;set;}
}
然后我的文件POCO变为:
public class Document : BaseEntity{
//Properties here
}
我的回购:
class Repository<T> : IRepository<T> where T : BaseEntity
{
private readonly PrincipalServerContext context;
private DbSet<T> entities;
public T Get(long id)
{
return entities.SingleOrDefault(s => s.ID == id);//Here is my problem
}
}
但是我不想理想地做到这一点。我在通用仓库中喜欢的是它允许我不为所有不同的表重复相同的代码(我有300+)。但拥有BaseEntity也意味着重组我已经做过的很多事情。 是否有可能在没有此BaseEntity类的情况下在任何POCO上应用Generic repo?
感谢您的帮助
答案 0 :(得分:4)
您正在调用Queryable.SingleOrDefault方法。
它的第二个参数的类型为Expression<Func<T, bool>>
,因此您可以使用as title属性手动构建表达式。
简短的例子:
public T Get(long id)
{
var idName = "ID" + typeof(T).Name; // For Document would be IDDocument
var parameter = Expression.Parameter(id.GetType());
var property = Expression.Property(parameter, idName)
var idValue = Expression.Constant(id, id.GetType());
var equal = Expression.Equal(property, idValue);
var predicate = Expression.Lambda<Func<T, bool>>(equal, parameter);
return entities.SingleOrDefault(predicate);
}
想象一下你写了lambda函数(T obj) => obj.IdProperty == id
。
此处obj
为parameter
,idName
应存储"IdProperty"
字符串。
property
表示obj.IdProperty
,idValue
表示id
的值。
equal
表示obj.IdProperty == id
,谓词表示整个表达式(T obj) => obj.IdProperty == id
。