Generic Repository 是否需要一个 Base Entity class 才能应用到所有地方?
Does a Generic Repository need a Base Entity class to be applied everywhere?
我正在使用 ASP.NET MVC 和 Onion Architecture 创建一个 Intranet 网站。我一直在实施存储库模式,但遇到了困难。
假设我有一个包含 IDDocument 的文档 table。那么这是我的回购协议(只有一种方法):
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 未被识别为来自文档 table。解决方案是创建一个 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
}
}
但是我不想这么理想。我喜欢通用存储库的一点是,它允许我不为所有不同的 table 重复相同的代码(我有 300+)。但是拥有一个 BaseEntity 也意味着重组很多我已经做过的事情。
是否可以拥有一个通用存储库,您可以在没有此 BaseEntity class 的情况下将其应用于任何 POCO?
感谢您的帮助
您正在调用 Queryable.SingleOrDefault 方法。
它的第二个参数的类型为 Expression<Func<T, bool>>
,因此您可以手动构建表达式,根据需要使用标识符 属性。
简短示例:
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
,predicate表示整个表达式(T obj) => obj.IdProperty == id
.
我正在使用 ASP.NET MVC 和 Onion Architecture 创建一个 Intranet 网站。我一直在实施存储库模式,但遇到了困难。
假设我有一个包含 IDDocument 的文档 table。那么这是我的回购协议(只有一种方法):
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 未被识别为来自文档 table。解决方案是创建一个 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
}
}
但是我不想这么理想。我喜欢通用存储库的一点是,它允许我不为所有不同的 table 重复相同的代码(我有 300+)。但是拥有一个 BaseEntity 也意味着重组很多我已经做过的事情。 是否可以拥有一个通用存储库,您可以在没有此 BaseEntity class 的情况下将其应用于任何 POCO?
感谢您的帮助
您正在调用 Queryable.SingleOrDefault 方法。
它的第二个参数的类型为 Expression<Func<T, bool>>
,因此您可以手动构建表达式,根据需要使用标识符 属性。
简短示例:
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
,predicate表示整个表达式(T obj) => obj.IdProperty == id
.