【问题标题】:asp.net - ef - generic service/repository patternasp.net - ef - 通用服务/存储库模式
【发布时间】:2018-01-10 10:12:34
【问题描述】:

我正在使用具有通用存储库类 EFRepositoryBase 的服务/存储库模式,其中 T : ModelBase, new() T 是 ef 中使用的所有 poco 继承的类。 EFRepositoryBase 有一个方法 Read

public IQueryable<T> Read()
{
        try
        {
            return db.Set<T>();
        }
        catch (Exception)
        {
            throw new IRepositoryException();
        }
}

每个服务都从具有 EFRepository 类型的 repo 属性的 ServiceBase 继承。

出于性能原因,我发现我最好使用 sql-view 来显示订单列表,因为该列表从其他表格中获取大量数据,具有计算字段,......为了测试这一点,我在sql, poco (OrderIndexItem) 映射到它,在上下文中添加了一个 DBset vwOrderIndex ...一切正常。问题是目前我直接在服务中处理 db.vwOrderIndex。下一步是使其通用。

这个想法是向 ModelBase 添加一个静态属性,其中包含相关的“视图 poco”的类型。

public static Type IndexItemType { get; set; } = null;

并为 Order 添加一个静态构造函数来设置该类型

static  Order()
{
    IndexItemType = typeof(OrderIndexItem);
}

在通用存储库中,我添加了一个额外的方法

    public IQueryable<TIndex> ReadIndex<TIndex>() where TIndex : ModelBase, IModelBaseIndexItem
    {
        try
        {
        }
        catch (Exception)
        {
            throw new IRepositoryException();
        }
    }

这个想法是通过静态属性 IndexItemType 返回与 T 关联的类型的 DbSet。

有什么想法吗?

另一个可接受的解决方案可能只是使用相关 IndexItemType f.e. 的命名约定。订单 - OrderIndexItem,成员 - MemberIndexItem,...

在这两种方法中我都无法解决的问题:如何返回适当的 DbSet?

第三种方法可能是将 EFRepositoryBase 更改为

public class EFRepositoryBase<T, TIndex> : IRepository<T, TIndex> where T : ModelBase, new() where TIndex : ModelBase, IModelBaseIndexItem, new()

虽然对代码的影响很大,所以我宁愿不使用这种方法,除非它是唯一的。

【问题讨论】:

  • 具体是什么问题?如果您只是在寻求一般的设计建议,那么恐怕这是错误的论坛。
  • 没有一般的模式建议。鉴于该订单有一个静态属性,用于保存视图的相关 poco。如何在通用存储库中返回该关联类型的数据库集。
  • 反思。你不能在运行时参数化泛型。
  • 反射不起作用,因为此时静态属性的值是未知的。

标签: c# entity-framework generics repository-pattern


【解决方案1】:

使用命名约定的可行解决方案:

public IQueryable<IModelBaseIndexItem> ReadIndex()
{
    try
    {
        Type TIndexItem = typeof(T).Assembly.GetType(typeof(T).FullName + "IndexItem");
        return (IQueryable<IModelBaseIndexItem>) db.Set(TIndexItem);
    }
    catch (Exception)
    {
        throw new IRepositoryException();
    }
}

【讨论】:

    【解决方案2】:

    最终我采用了以下解决方案,不将存储库限制为每个 ModelBase POCO 的一种视图。

       public IQueryable<TSqlView> ReadSqlView<TSqlView>() where TSqlView : ISqlViewItem, new()
        {
            try
            {
                return (IQueryable<TSqlView>)Db.Set( typeof(TSqlView));
            }
            catch (Exception)
            {
                throw new IRepositoryException();
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-12
      • 2011-07-19
      • 1970-01-01
      相关资源
      最近更新 更多