【发布时间】:2014-08-11 20:25:11
【问题描述】:
我目前从事的项目使用 Linq to SQL 作为一种 ORM 数据访问技术。它是一个 MVC3 Web 应用程序。我面临的问题主要是由于无法模拟(用于测试)由 DBML 设计器自动生成的 DataContext。
所以为了解决这个问题(经过大量阅读),我重构了现有的存储库系统 - 单个存储库,每个表都有单独和重复的访问方法,最终有 300 种方法,其中只有 10 种是唯一的 - 成具有通用方法的单个存储库获取表并将更多通用类型返回到应用程序的上游。 DataContext 现在已被包装,并且可以轻松模拟。
[编辑:为了实现这一点,巧合的是,我使用了下面 Jacob 提供的链接!]
我的问题更多地围绕着我迄今为止所使用的设计以及我在应用程序结构中注意到的差异。
1) 重构了使用经典 Linq to SQL 查询的代码:
public Billing GetBilling(int id)
{
var result = (
from bil in _bicDc.Billings
where bil.BillingId == id
select bil).SingleOrDefault();
return (result);
}
现在看起来像:
public T GetRecordWhere<T>(Expression<Func<T, bool>> predicate) where T : class
{
T result;
try
{
result = _dataContext.GetTable<T>().Where(predicate).SingleOrDefault();
}
catch (Exception ex)
{
throw ex;
}
return result;
}
控制器使用如下查询:
_repository.GetRecordWhere<Billing>(x => x.BillingId == 1);
这很好,正是我想要实现的目标。
...但是....我还必须执行以下操作才能准确获得控制器类中所需的结果集(本质上是应用程序的最高点)...
viewModel.RecentRequests = _model.GetAllRecordsWhere<Billing>(x => x.BillingId == 1)
.Where(x => x.BillingId == Convert.ToInt32(BillingType.Submitted))
.OrderByDescending(x => x.DateCreated).
Take(5).ToList();
这 - 据我的理解是正确的 - 现在使用 Linq to Objects 而不是我以前使用的 Linq to SQL 查询?这可以练习吗?我感觉不对,但我不知道为什么。可能是因为查询的逻辑位于应用程序的最高层,而不是最低层,但是……我听从各位好人的建议。我考虑的问题之一是将整个表放入内存,但我知道使用 Iqeryable 返回类型会将 where 子句带到数据库并在那里进行评估。因此只返回我需要的结果集......我可能是错的。
如果你已经做到了这一步,那就太好了。谢谢,如果您有任何建议,非常感谢!
更新:根据要求包含 GetAllRecordsWhere 方法
public IQueryable<T> GetAllRecordsWhere<T>(Expression<Func<T, bool>> predicate) where T : class
{
return _dataContext.GetTable<T>().Where(predicate);
}
使用:
public IQueryable<TName> GetTable<TName>() where TName : class
{
return _db.GetTable<TName>().AsQueryable();
}
【问题讨论】:
-
GetAllRecordWhere 返回什么?应该是
IQueryable<T>。 -
它确实是一个 IQueryable
,正如我在帖子末尾提到的那样 - 我相信我在某处读到过使用 IQueryable 调用的后续 .Where(predicate) 等调用在调用时会被评估而不是将很多东西拉入记忆?不管这是不是真的…… -
只是吹毛求疵:GetRecordWhere 中的 try-catch 是多余的 - 是否已为示例进行了简化?同样,如果
GetAllRecordsWhere照它说的做,` 那么 .Where(x => x.BillingId == Convert.ToInt32(BillingType.Submitted)) 行就相当于.Where(x => 1 == Convert.ToInt32(BillingType.Submitted))- 对吗? -
@saus 正确,在这两个方面。
-
您可能需要发布您的 GetAllRecordsWhere
的签名。是 Expression > 还是 Func 如果是后者,那么 LINQ to Objects 将被使用,因为接受 Func 的 Where 版本扩展了 IEnumerable,而不是 IQueryable .
标签: c# linq-to-sql linq-to-objects