【问题标题】:Does a Generic Repository need a Base Entity class to be applied everywhere?通用存储库是否需要在任何地方应用基本实体类?
【发布时间】:2017-11-19 09:09:27
【问题描述】:

我正在使用 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
    }
}

问题是我不能使用它,因为 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 上应用的通用存储库?

感谢您的帮助

【问题讨论】:

  • 你至少需要一个接口来给编译器一些关于&lt;T&gt;的信息
  • 当您的泛型类采用 T : class 时,您如何期望您的代码知道 ID 是什么?
  • @DanielA.White 好的,谢谢
  • @maccettura 这就是我的问题的重点......
  • @Flexabustbergson 使用必须具有特定形状(即具有 ID)的泛型时,您需要提供通用类型。无论是接口、抽象类,还是其他类继承自的常规类。在某些时候,您需要找出所有类之间的共性,如果没有,那么您不应该使用泛型来尝试强制它们都相同(当然,除非您不需要访问任何泛型类中的成员/属性,那么它们实际上是什么形状并不重要)。

标签: c# repository-pattern onion-architecture


【解决方案1】:

您正在调用Queryable.SingleOrDefault 方法。

它的第二个参数的类型为Expression&lt;Func&lt;T, bool&gt;&gt;,因此您可以手动构建表达式,根据需要使用标识符属性。

简短示例:

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) =&gt; obj.IdProperty == id。 这里objparameteridName 应该存储"IdProperty" 字符串。 property 表示obj.IdPropertyidValue 表示id 的值。 equal 表示obj.IdProperty == id,谓词表示整个表达式(T obj) =&gt; obj.IdProperty == id

【讨论】:

  • 哇,这正是我想要的!谢谢楼主!
  • 这是书签。这是我第一次看到表达式树的解释方式真正让它们非常有用。
猜你喜欢
  • 2020-12-31
  • 2017-05-16
  • 1970-01-01
  • 2022-01-27
  • 2015-07-20
  • 2019-01-17
  • 2011-07-03
  • 1970-01-01
  • 2017-08-26
相关资源
最近更新 更多