在这个版块中我来谈谈几种使用LINQ TO SQL时,提升效率的方法。

(本版块会不断更新,大家共同学习进步)

 

(DataContext 实例下有个 Log 属性通过设置此属性能看到,LINQ 生成的SQL代码,一下代码将用到此技巧)

1.使用延迟。

(1)延迟执行和立即执行:延迟执行不仅仅是LINQ TO SQL独有的,基本上所有的LINQ都具有此特性,它能提高效率让我们在适当的时间执行适当的查询,如果在某些特殊的情况下不想使用此特性可以使用ToList() or ToArray()方法让该查询立即执行。

示例1:延迟执行

NorthwndDataContext dc = new NorthwndDataContext();
            dc.Log = Console.Out;
            var query = from c in dc.Customers
                select c;
            Console.WriteLine("this is deferred execute.");

            foreach (var item in query)
            {
                Console.WriteLine(item.CustomerID);
                Console.ReadKey();
            }

结果:

this is deferred execute.
SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactT
itle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Coun
try], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1

ALFKI

示例2:不延迟执行

NorthwndDataContext dc = new NorthwndDataContext();
            dc.Log = Console.Out;
            var query = (from c in dc.Customers
                select c).ToList();
            Console.WriteLine("this is not deferred execute.");

            foreach (var item in query)
            {
                Console.WriteLine(item.CustomerID);
                Console.ReadKey();
            }

结果:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactT
itle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Coun
try], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1

this is not deferred execute.
ALFKI

(注意黄色标注的位置,就能很清楚延迟和普通执行的区别了)

(2)延迟加载和立即加载:在C#代码中往往会使用对象实例的属性去和其他对象建立关系(Customer.Order),但有时我们需要同时需要一个完整的对象链的信息,往往只要当前对象的信息,因此我们能通过延迟加载和立即加载来实现不同的需求。

(通过DataLoadOptions实例去实现 )

实例1:延迟加载

var query = (from c in dc.Customers
                select c).ToList();

            foreach (var item in query)
            {
                Console.WriteLine(item.CustomerID);
                Console.WriteLine("this is deferred load.");
                foreach (var o in item.Orders)
                {
                    Console.WriteLine(o.OrderID);
                }
                Console.ReadKey();
            }

结果:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactT
itle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Coun
try], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1

ALFKI
this is deferred load.
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [
t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[Sh
ipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPosta
lCode], [t0].[ShipCountry]
FROM [dbo].[Orders] AS [t0]
WHERE [t0].[CustomerID] = @p0
-- @p0: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [ALFKI]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1

10643
...

实例2:立即执行

NorthwndDataContext dc = new NorthwndDataContext();
            dc.Log = Console.Out;

            DataLoadOptions lo = new DataLoadOptions();
            lo.LoadWith<Entity.Customer>(c => c.Orders);
            dc.LoadOptions = lo;

            var query = (from c in dc.Customers
                select c).ToList();

            foreach (var item in query)
            {
                Console.WriteLine(item.CustomerID);
                Console.WriteLine("this is deferred load.");
                foreach (var o in item.Orders)
                {
                    Console.WriteLine(o.OrderID);
                }
                Console.ReadKey();
            }


 结果:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactT
itle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Coun
try], [t0].[Phone], [t0].[Fax], [t1].[OrderID], [t1].[CustomerID] AS [CustomerID
2], [t1].[EmployeeID], [t1].[OrderDate], [t1].[RequiredDate], [t1].[ShippedDate]
, [t1].[ShipVia], [t1].[Freight], [t1].[ShipName], [t1].[ShipAddress], [t1].[Shi
pCity], [t1].[ShipRegion], [t1].[ShipPostalCode], [t1].[ShipCountry], (
    SELECT COUNT(*)
    FROM [dbo].[Orders] AS [t2]
    WHERE [t2].[CustomerID] = [t0].[CustomerID]
    ) AS [value]
FROM [dbo].[Customers] AS [t0]
LEFT OUTER JOIN [dbo].[Orders] AS [t1] ON [t1].[CustomerID] = [t0].[CustomerID]
ORDER BY [t0].[CustomerID], [t1].[OrderID]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1

ALFKI
this is deferred load.
10643

...

 (同样可以看到2者的差别,注意使用这种延迟加载,要在对应的实体类里为要做映射的类使用EntityRef和EntitySet包装,

对实体类映射的某个字段做延迟加载要使用Link包装

 

2.编译查询:往往一个查询表达式要被重复使用很多次,如果每次都反复的生成表达式树,然后生成SQL语句势必开销很大,效率很低。因此可以使用编译查询,它把不变的部分编译好,把需要改变的部分再进去就OK了。

示例:

            //编译查询核心
            var query1 = CompiledQuery.Compile((NorthwndDataContext dc1, string initialChar) =>
                from c in dc1.Customers
                where c.CustomerID.StartsWith(initialChar)
                select c);

            foreach (var item1 in new[] { "A", "B", "C", "D" })
            {
                //调用方法
                var query = query1(dc, item1);
                foreach (var item in query)
                {
                    Console.WriteLine("Customer Id :{0}", item.CustomerID);
                }
            }

以上方法请在适合的地方选择性使用,这样才能提高效率。其他能提高LINQ TO SQL的效率和方法会在今后继续补充