通用存储库是否需要在任何地方应用基本实体类?

Fle*_*son 1 c# repository-pattern onion-architecture

我正在使用 ASP.NET MVC 和Onion Architecture创建一个 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
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是我不能使用它,因为 T 未被识别为来自 Document 表。解决方案是创建一个 BaseEntity:

public class BaseEntity{
  public int ID{get;set;}
}
Run Code Online (Sandbox Code Playgroud)

然后我的文档 POCO 变为:

public class Document : BaseEntity{ 
   //Properties here
}
Run Code Online (Sandbox Code Playgroud)

还有我的回购:

 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
        }
    }
Run Code Online (Sandbox Code Playgroud)

我不想在理想情况下这样做。我喜欢通用存储库中的一点是,它允许我不必为所有不同的表(我有 300 多个)重复相同的代码。但是拥有 BaseEntity 也意味着重构我已经完成的很多工作。是否可以有一个通用存储库,您可以在没有此 BaseEntity 类的情况下将其应用于任何 POCO?

谢谢你的帮助

Mar*_*nko 5

您正在调用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);
}
Run Code Online (Sandbox Code Playgroud)

假设您编写了 lambda 函数(T obj) => obj.IdProperty == id。这objparameter, 并且idName应该存储"IdProperty"字符串。 property表示obj.IdPropertyidValue表示值 if idequal表示obj.IdProperty == id,而 predicate 表示整个表达式(T obj) => obj.IdProperty == id