LINQ To SQL分页失败后会有什么结果呢?关于使用LINQ To SQL分页有什么需要注意的么?LINQ To SQL分页的实质是什么呢?那么本文就向你介绍具体的内容。
从微软发布Linq To SQL依此,程序员围绕其与SqlDataAdapter等相比进行讨论,根据CSDN上的报道,LINQ比SqlDataReader落后的速度不超过10%。更加相信微软对Linq性能的分析会结合算法和统计结果来比较,对于linq查询性能--博客园的黄昕已经有所分析。于是产生想实验一下Linq和SqlDataAdapter等分别在大数据量下进行分页。园子里的Yzl的研究室已经对Linq分页可能出现的问题提出一种情况。(以下只是实验过程并非测试所以没有benchmark).
LINQ To SQL分页实验步骤:LINQ To SQL分页之对于数据库:
数据库名People;数据表名Prof 包括ID Name Age三个字段;记录数 10万条(也许不是很足够)下面的数据库代码并非最佳方案,大家贴一下自己的
CREATE DATABASE People
ON
Primary
(
NAME='people',
FILENAME='D:\people_Data.mdf',
SIZE=10,
FILEGROWTH=10%
)
LOG ON
(
NAME='peoplelog',
FILENAME='D:\people_Log.ldf',
SIZE=10,
FILEGROWTH=10%
)
GO
USE People
CREATE TABLE Prof
(
ID INT IDENTITY(1,1) NOT NULL,
Name NVARCHAR(100) COLLATE Chinese_PRC_CI_AS NULL ,
Age INT NULL,
)
GO
SET IDENTITY_INSERT Prof ON
DECLARE @i INT,@age INT
SET @i=1
WHILE @i<=100000
BEGIN
SET @age=CAST((RAND()*(100-20)+20)AS INT)
INSERT INTO Prof(ID,Name,Age)
VALUES(@i,'Name_'+ CAST(@age AS NVARCHAR),@age)
SET @i=@i+1
END
SET IDENTITY_INSERT Prof OFF
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
测试代码一(SQL部分):
网上已经有很多非常好的分页算法,各人按照设计的需要选择合适的为好,特别提一下Thin的算法(很简洁),测试中采用了李洪根发布的其中一种分页算法
DivPage
//省略行参数设置和拼接
string strcmd = "SELECT TOP 20 * " +
"FROM Prof " +
"WHERE (ID >" +
"(SELECT MAX(ID) FROM (
SELECT TOP 60000 id FROM Prof ORDER BY id) AS T)) ORDER BY ID";
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
显示查询耗时:00:00:00.0322245
测试代码二(Linq部分)
Linq To SQL的分页主要通过Skip和Take操作符实现,代码如下:
//省去设置参数
//分页Skip(PageSize * PageIndex).Take(PageSize)
PeopleDataContext dc = new PeopleDataContext();
var query =
(from p in dc.Prof select p).Skip(60000).Take(20);
- 1.
- 2.
- 3.
- 4.
- 5.
然而却出现异常:此提供程序只支持对返回实体或投影(包含所有标识列)的有序查询使用 Skip(),这种查询为单表(非联接)查询,或者为 Distinct、Except、Intersect 或Union (非 Concat)操作。第一次遇到这种异常(当然很多朋友并不会,而且已经看出问题所在了),查找Skip的定义
public static IEnumerable<TSource> Skip<TSource>(
this IEnumerable<TSource> source,
int count
)
- 1.
- 2.
- 3.
- 4.
此方法通过使用延迟执行实现。即时返回值为一个对象,该对象存储执行操作所需的所有信息。只有通过直接调用对象的 GetEnumerator 方法或使用 Visual C# 中的 foreach(或 Visual Basic 中的 For Each)来枚举该对象时,才执行此方法表示的查询。再看一下该查询生成的SQL代码:
SELECT TOP 20 [t0].[ID], [t0].[Name], [t0].[Age]
FROM [dbo].[Prof] AS [t0]
WHERE NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM (
SELECT TOP 60000 [t1].[ID]
FROM [dbo].[Prof] AS [t1]
) AS [t2]
WHERE [t0].[ID] = [t2].[ID]
))
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
Skip查询需要数据标识列提供查询的根据,是否可以假设Skip是通过标识列的唯一性来逐一返回对象的呢?
修改数据库People表Prof,设置其ID为主键,(上面的数据库相应修改为)
ALTER TABLE Prof
ADD CONSTRAINT PK_ID PRIMARY KEY (ID)
GO
- 1.
- 2.
- 3.
再次运行,显示查询耗时:00:00:00.0478485
LINQ To SQL分页问题的提出:
1.为什么两次查询的耗时相差那么大呢?(估计是个人机器以及代码问题:))
2.Skip是否通过主键的唯一性逐次返回查询对象?
LINQ To SQL分页总结:
SQLServer的执行效率是按照语义来执行的,也许Linq在性能上不一定和SQLDataAdapter等完全一样,但是在开发效率上,我们可以看出Linq的实现代码的简易性是相对较好的,只要克服其中的一些问题,相信Linq会为以后的数据查询提供更强大帮助!
LINQ To SQL相关的内容就向你介绍到这里,希望对你了解和学习LINQ To SQL有所帮助。
【编辑推荐】