我正在使用具有通用存储库类的服务/存储库模式
EFRepositoryBase<T>
其中T:ModelBase,new()
T 是 ef 中使用的所有 poco 继承的类。
EFRepositoryBase 有一个方法 Read
public IQueryable<T> Read()
{
try
{
return db.Set<T>();
}
catch (Exception)
{
throw new IRepositoryException();
}
}
每个服务都继承自
ServiceBase<T>
具有类型为 EFRepository<T>
. 的 repo 属性
出于性能原因,我发现我最好使用 sql-view 来显示订单列表,因为该列表从其他表中获取大量数据,具有计算字段,......为了测试这一点,我在 sql 中创建了一个视图,poco (OrderIndexItem) 映射到它,添加一个
DBset<OrderIndexItem>
vwOrderIndex 到上下文......一切正常。问题是目前我直接在服务中处理 db.vwOrderIndex。下一步是使它通用。
想法是向 ModelBase 添加一个静态属性,其中包含相关“view 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()
虽然对代码的影响很大,所以我宁愿不使用这种方法,除非它是唯一的。
使用命名约定的工作解决方案:
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();
}
}
最终我采用了以下解决方案,不将存储库限制为每个 ModelBase POCO 的一种视图。
public IQueryable<TSqlView> ReadSqlView<TSqlView>() where TSqlView : ISqlViewItem, new()
{
try
{
return (IQueryable<TSqlView>)Db.Set( typeof(TSqlView));
}
catch (Exception)
{
throw new IRepositoryException();
}
}