首页 > 代码库 > Linq的延迟加载问题

Linq的延迟加载问题

什么是延迟加载:所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。可以简单理解为,只有在使用的时候,才会发出sql语句进行查询,数据是分N次读取。

什么是立即加载:所谓立即加载既是所有的相关数据一次被读取出来,而不是分N次。

相信上面的概念大家都知道,接下来举个例子说明一下:

ClassInfo表:

StuInfo表:

2个表的关系就不要我多说了

一、接下来看延迟加载代码:

    LinqDBDataContext db = new LinqDBDataContext();        db.DeferredLoadingEnabled = true;//true表示延迟加载,默认就是延迟加载,所以本句代码可以省略        string path = Server.MapPath(@"~/Log/log.txt");        StreamWriter sw = File.AppendText(path);        db.Log = sw;        //创建Linq to sql语句        var list = from s in db.ClassInfo                   select s;        //编辑SQL语句        foreach (var c in list)        {            string s1 = string.Format("班级ID:{0},班级名称:{1}<br>", c.ClassID, c.ClassName);            Response.Write(s1);            foreach (var mark in c.StuInfo)            {                string s2 = string.Format("学号:{0},姓名:{1}<br>", mark.StuNum, mark.StuName);                Response.Write(s2);            }        }        db.Log.Flush();        db.Log.Close();

输出的结果是:

班级ID:1,班级名称:T1001
学号:S001,姓名:张小三
学号:S004,姓名:王五
学号:S006,姓名:小明
学号:S007,姓名:郭晓明
学号:S009,姓名:张宝
班级ID:2,班级名称:T1002
学号:S002,姓名:李四
学号:S003,姓名:小丽
学号:S008,姓名:张洁
学号:S011,姓名:王燕
学号:S012,姓名:王胜
班级ID:3,班级名称:T1003
学号:S005,姓名:赵六
学号:S010,姓名:陈明
班级ID:4,班级名称:T1004
学号:S013,姓名:王倩

日志输出的内容如下:

SELECT [t0].[ClassID], [t0].[ClassName]FROM [dbo].[ClassInfo] AS [t0]-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.18058SELECT [t0].[StuNum], [t0].[StuName], [t0].[StuAge], [t0].[StuSex], [t0].[ClassID]FROM [dbo].[StuInfo] AS [t0]WHERE [t0].[ClassID] = @p0-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [1]-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.18058SELECT [t0].[StuNum], [t0].[StuName], [t0].[StuAge], [t0].[StuSex], [t0].[ClassID]FROM [dbo].[StuInfo] AS [t0]WHERE [t0].[ClassID] = @p0-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [2]-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.18058SELECT [t0].[StuNum], [t0].[StuName], [t0].[StuAge], [t0].[StuSex], [t0].[ClassID]FROM [dbo].[StuInfo] AS [t0]WHERE [t0].[ClassID] = @p0-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [3]-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.18058SELECT [t0].[StuNum], [t0].[StuName], [t0].[StuAge], [t0].[StuSex], [t0].[ClassID]FROM [dbo].[StuInfo] AS [t0]WHERE [t0].[ClassID] = @p0-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [4]-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.18058

通过日志可以看出来,外层的foreach是遍历ClassInfo,产生了查询ClassInfo的一句日志,里层foreach是遍历每个ClassInfo里面的StuInfo,由于有4个班,要查询4个ClassInfo里面的StuInfo,所以会产生4句日志。这种情况就是真正需要数据时,才进行查询。

 

二、接下来看立即加载的代码:

 

    LinqDBDataContext db = new LinqDBDataContext();        db.DeferredLoadingEnabled = false;//false表示立即加载        string path = Server.MapPath(@"~/Log/log.txt");        StreamWriter sw = File.AppendText(path);        db.Log = sw;        //立即加载模式(下面3句代码一定要加,否则学生信息查不到数据)        DataLoadOptions dl = new DataLoadOptions();        dl.LoadWith<ClassInfo>(s => s.StuInfo);        db.LoadOptions = dl;        //创建Linq to sql语句        var list = from s in db.ClassInfo                   select s;        //编辑SQL语句        foreach (var c in list)        {            string s1 = string.Format("班级ID:{0},班级名称:{1}<br>", c.ClassID, c.ClassName);            Response.Write(s1);            foreach (var mark in c.StuInfo)            {                string s2 = string.Format("学号:{0},姓名:{1}<br>", mark.StuNum, mark.StuName);                Response.Write(s2);            }        }        db.Log.Flush();        db.Log.Close();

 

输出来的结果和上面的一样,但是我们看看日志信息:

SELECT [t0].[ClassID], [t0].[ClassName], [t1].[StuNum], [t1].[StuName], [t1].[StuAge], [t1].[StuSex], [t1].[ClassID] AS [ClassID2], (    SELECT COUNT(*)    FROM [dbo].[StuInfo] AS [t2]    WHERE [t2].[ClassID] = [t0].[ClassID]    ) AS [value]FROM [dbo].[ClassInfo] AS [t0]LEFT OUTER JOIN [dbo].[StuInfo] AS [t1] ON [t1].[ClassID] = [t0].[ClassID]ORDER BY [t0].[ClassID], [t1].[StuNum]-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.18058

很明显立即加载,是一次性进行查询读取出来的。

 

Linq的延迟加载问题