【IT168技术文档】
这是我决定将LINQ to SQL集成到应用程序中一开始就一直在考虑的一个问题, 到底应该返回IQueryable<T>还是IQueryable? 或许这个列表还应该继续扩展为T,List<T>, object[], 对于Business Layer来说, 到底应该选择哪一种?
我最后的选择是T和IQueryable<T>, T很明显是针对于单个实体对象, 我认为针对只返回一个确定对象的情况下, 客户端很少需要再次利用IQueryable的能力进行二次筛选和操作, 而且方法体可以明确表明就是这返回一个对象或者null, 这一点我想应该没有太多异议.
对于集合列表, 的确是一个很难得选择, 我一次试图直接返回List, 这是很直观的, 因为2.0的时候我一直就是这么干的, 所以很自然我认为LINQ to SQL不应该有什么问题会阻止我这么做? 实际上, 这也的确没有什么太多的问题, 例如:
var q = from c in dataContext.ClaimRequests
where c.NextProcessedBy == userID && c.CurrentState == state
select c;
return q.ToList<ClaimRequest>();
ok, 进一步的需求来了, 首先我需要一个分页功能; 到这一步的时候我又有几个选择, 利用LINQ to SQL可以执行自定义存储过程的功能, 完全自己写, 这个可以工作很好, 问题是我很懒, 更重要的时候LINQ to SQL本身已经有API提供了分页功能了, 我有什么理由放弃, 除非性能真的到了非常Critical的时候, 看看下面的分页API, 多么简单:
return q.Skip<ClaimRequest>((currentPage - 1) * pageSize).Take<ClaimRequest>(pageSize)
生成的T-SQL语句:
SELECT [t2].[ClaimRequestID], [t2].[ClaimNumber], [t2].[ClaimName], [t2].[DateSubmitted], [t2].[SubmittedBy], ([t2].[LastName] + @p2) + [t2].[FirstName] AS [SubmittedUserName]
FROM (
SELECT TOP (10) [t0].[ClaimRequestID], [t0].[ClaimNumber], [t0].[ClaimName], [t0].[SubmittedBy], [t0].[DateSubmitted], [t1].[FirstName], [t1].[LastName]
FROM [dbo].[ClaimRequest] AS [t0]
INNER JOIN [dbo].[Users] AS [t1] ON [t1].[UserID] = [t0].[SubmittedBy]
WHERE ([t0].[NextProcessedBy] = @p0) AND ([t0].[CurrentState] = @p1)
) AS [t2]
– @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [jlv]
– @p1: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [New]
– @p2: Input NVarChar (Size = 2; Prec = 0; Scale = 0) [, ]
DLINQ生成的SQL语句是利用TOP和嵌套子查询, 这种方法已经被证明是比较高效的做法(相比于临时表的做法), 所以完全有理由可以一试.到这里, List, IQueryable, IQueryable都没有任何问题.
接下来我还需要一个动态排序功能, 这里List的局限性出来了, 传统的做法可能需要用一个dynamic参数来传递需要排序的列然后到SP当中来执行, 但这里我们已经不打算使用SP了, 也没有动态sql语句, 所有的东西都是强类型的, 然后有LINQ to SQL在运行时来帮我们转换为T-SQL语句。首先List的话, 我们不知道到底哪个字段要排序, 如果使用字符串作为参数的话, 例如放一个string sortBy作为方法的参数, 那么在方法体内就需要做if…else或者switch的判断, 而且还要考虑倒序还是正序的排序要求, 而且你还要hard code,很明显麻烦来了.
然而如果使用IQueryable却可以很好的解决所有的这些问题. 这里需要说明一下IQueryable<T>和IQueryable, 在没有涉及排序之前, 我想当然的选择了IQueryable, 原因是我不想返回实体类的所有字段以及它的Association类的所有字段,因为这样可以提供更好的性能, 所以自然而然的我选择了返回匿名类, 类似这样:
var q = from c in dataContext.ClaimRequests
where c.NextProcessedBy == userID && c.CurrentState == “New”
select new {ClaimRequestID = c.ClaimRequestID,
ClaimNumber = c.ClaimNumber,
ClaimName = c.ClaimName,
DateSubmitted = c.DateSubmitted,
SubmittedBy = c.SubmittedBy,
SubmittedUserName = c.User.LastName + “, “ + c.User.FirstName};