ֲ»ASP.NET»Ϊʲô˵ LINQ Ҫʤ SQL

Ϊʲô˵ LINQ Ҫʤ SQL

Դoschina ʱ䣺2017-03-01 Ķֲ

㻹ûг LINQͻɶСֵġSQL ûлΪʲôҪ޲? ΪʲôǻҪһֲѯ?

ֲ

е˵ LINQ ͬ C# VBһ𣬹ʶ˱Ժݿ֮ϵĺ蹵ͬʱΪԴṩ˵һIJѯӿڡȻЩʵǹµһšҪǣҪݿвѯʱLINQ ڴ¶ SQL ԽЧ

ͬ SQL ȣ LINQ ӡҸ߼Ӹ C# ͬ C++ ģʱʹ C++ Ȼõѡ񣨺ñʹ SQL ijڴУʹִԶΪײϸڲһʤ

SQL һźǹϵ— 1974 ꡣȻչûбƹʹе— VB6 Visual FoxProҲѾϰڴκδ©ĵط!

һӡҪдһӵIJѯȡͻݣ£

SELECT UPPER(Name)
FROM Customer
WHERE Name LIKE 'A%'
ORDER BY Name

ڼҪЩṩӦһҳȡ 21 30 ݡҪһӲѯ

SELECT UPPER(Name) FROM
(
   SELECT *, RN = row_number()
   OVER (ORDER BY Name)
   FROM Customer
   WHERE Name LIKE 'A%'
) A
WHERE RN BETWEEN 21 AND 30
ORDER BY Name

Ҫְ֧汾 SQL Server 2005 ֮ǰģϵݿ⣬:

SELECT TOP 10 UPPER (c1.Name)
FROM Customer c1
WHERE
   c1.Name LIKE 'A%'
   AND c1.ID NOT IN
   (
      SELECT TOP 20 c2.ID
      FROM Customer c2
      WHERE c2.Name LIKE 'A%'
      ORDER BY c2.Name
   ) 
ORDER BY c1.Name

ӴңҲΥ DRY ԭʹ LINQ ʵͬIJѯЧȻڼϸʤһ

var query =
   from c in db.Customers
   where c.Name.StartsWith ("A")
   orderby c.Name
   select c.Name.ToUpper();

var thirdPage = query.Skip(20).Take(10);

ֻеöٵ thirdPage ʱѯŻʵִСڴ LINQ SQL Entity Framework ijУὫ϶ɵģѯתһ SQL 䣬ӵݿŻġ

Ѿע⵽ LINQ һ΢΢ش󣩵档ѡеѯ裺

IQueryable<T> Paginate<T> (this IQueryable<T> query, int skip, int take)
{
   return query.Skip(skip).Take(take);
}

ǿ

var query = ...
var thirdPage = query.Paginate (20, 10);

ҪǣǿԽķҳѯ֮ͨ LINQ ԰ѲѯһţȻӦóá

LINQ һԲ JOIN ܽйϵѯ磬Ҫгй $1000 ϣҾסڻʢٵˡǻٶùĿҲǾIJɹ/ĿɹҰѣû˼¼ģֽҲҪĸPurchase, Customer, Address Լ PurchaseItem֮вѯʹ LINQIJѯѴ֮

from p in db.Purchases
where p.Customer.Address.State == "WA" || p.Customer == null
where p.PurchaseItems.Sum (pi => pi.SaleAmount) > 1000
select p

ͬȹЧ SQL

SELECT p.*
FROM Purchase p
    LEFT OUTER JOIN 
        Customer c INNER JOIN Address a ON c.AddressID = a.ID
    ON p.CustomerID = c.ID	
WHERE
   (a.State = 'WA' || p.CustomerID IS NULL)
    AND p.ID in
    (
        SELECT PurchaseID FROM PurchaseItem
        GROUP BY PurchaseID HAVING SUM (SaleAmount) > 1000
    )

ԴһչҪǮУյͶӰʾԱԼĿǿȻظرЩIJѯ

from p in db.Purchases
where p.Customer.Address.State == "WA" || p.Customer == null
let purchaseValue = p.PurchaseItems.Sum (pi => pi.SaleAmount)
where purchaseValue > 1000
orderby purchaseValue descending
select new
{
   p.Description,
   p.Customer.SalesPerson.Name,
   PurchaseItemCount = p.PurchaseItems.Count()
}

ʹ SQL ʵͬIJѯ

SELECT 
    p.Description,
    s.Name,
    (SELECT COUNT(*) FROM PurchaseItem pi WHERE p.ID = pi.PurchaseID) PurchaseItemCount	
FROM Purchase p
    LEFT OUTER JOIN 
        Customer c 
            INNER JOIN Address a ON c.AddressID = a.ID
            LEFT OUTER JOIN SalesPerson s ON c.SalesPersonID = s.ID
    ON p.CustomerID = c.ID	
WHERE
    (a.State = 'WA' OR p.CustomerID IS NULL)
    AND p.ID in
    (
        SELECT PurchaseID FROM PurchaseItem
        GROUP BY PurchaseID HAVING SUM (SaleAmount) > 1000
    )
ORDER BY
    (SELECT SUM (SaleAmount) FROM PurchaseItem pi WHERE p.ID = pi.PurchaseID) DESC

˼ǿԽ SQL ѯתص LINQɵIJѯÿһ鶼ɵʽظ̳ﳣIJѯͨǷİ汾—— SQL ˼ LINQ ˼Ľǽ Fortran ת C# 6 ʱ߿ GOTO ׾﷨һ

ڲѯдӶѡ - յĽһƽΪԪԪ顣ʹ˶ SQLΪ²ᷢ——ظӶʹý޷ڿͻ˺ܺõʹáԵʱԽܡ෴LINQ Իȡķֲ㼶ݡֹظý״óͷڴҲϲҪ磬Ҫȡһˣÿһ¼ǵĸ߼ֵסʹ LINQ

from c in db.Customers
where c.Address.State == "WA"
select new
{
   c.Name,
   c.CustomerNumber,
   HighValuePurchases = c.Purchases.Where (p => p.Price > 1000)
}

HighValuePurchasesһ͡DzѯһԣͲҪˡһվϵϸͱܺõijˡڴУ SQLܾһϣLINQ ΪͷصԪؾųСҪһԷһϵĹߣ:

from c in db.Customers
where c.Address.State == "WA"
let HighValuePurchases = c.Purchases.Where (p => p.Price > 1000)where HighValuePurchases.Any()select new
{
   c.Name,
   c.CustomerNumber,
   HighValuePurchases
}

LINQ ͨһ鸻IJƽϡϡѯԼֲͲѯ֧֡

Ҫ֮ǰӲأ"WA"״̬DzǾҪһ? ʵֻҪͿ:

string state = "WA";

var query =
   from c in db.Customers
   where c.Address.State == state
   ...

DbCommand IJߵ SQL ע빥 LINQ IJҸ߶ȿɶġ——ҽúܲ

Ϊ LINQ ѯʱԽϣǿνʡ磬дһҪ죬£

IQueryable<Customer> GetCustomers (string state, decimal? minPurchase)
{
    var query = Customers.AsQueryable();
    
    if (state != null)
        query = query.Where (c => c.Address.State == state);
    
    if (minPurchase != null)
        query = query.Where (c => c.Purchases.Any (p => p.Price > minPurchase.Value));
    
    return query;
}

ʹÿյ state Լ minPurchase ֵҪ죬ôöٽʱ SQL ͻᱻɳ

SELECT [t0].[ID], [t0].[Name], [t0].[AddressID]
FROM [Customer] AS [t0]

⣬ָ state minPurchase ֵLINQ SQL ͲֻѯνʣҪ䣺

SELECT [t0].[ID], [t0].[Name], [t0].[AddressID]
FROM [Customer] AS [t0]
LEFT OUTER JOIN [Address] AS [t1] ON [t1].[ID] = [t0].[AddressID]
WHERE (EXISTS(
    SELECT NULL AS [EMPTY]
    FROM [Purchase] AS [t2]
    WHERE ([t2].[Price] > @p0) AND ([t2].[CustomerID] = [t0].[ID])
    )) AND ([t1].[State] = @p1)

ΪǵҪ췵һ IQueryableѯöٵ֮ǰᱻʵʵת SQL ִС͸˵ýһνʡҳԽ˵ͶӰȵȵʱ

̬

֮ǰIJѯУǽ state һһַôѯڱʱͻᱨõȵʱҲͬڰѱŪعʱһʵڵ棺ûͷ飬ʾ

ͻ˴óͷ

LINQ ɵؽѯһЩתƵͻϽдóͷڸؼ縺ϴݿʵܡֻҪȡû裨֮վҪڷˣͿԾԵͨѶԽתԼѹתƵؽٵӦ÷ȥʹ LINQҪľ AsEnumerable() תƵѯ֮УǸ֮鶼ڵִС

ʲôʱ LINQ ȥѯݿ

LINQ ĹЧǿ󣬵ȡ SQL 95% ϵ󣬲ʱȻҪSQL:

  • ҪֶIJѯ (ҪŻͽʾʱ)

  • Щ漰Ҫ select ʱȻҪЩвѯIJѯ

  • Ԥ֪ĸԼ

оõʱվҪ SQL (ʹ LINQ ʱĹ߲ǾҪҪʹô洢̺ͺʱSQL Dzлȱ)ͨ SQL бдֵ SQL LINQ һ, ȻԽӴ LINQ ѯЩ

˽ŲѯԲ⣬Ϊ㶼Ҫȥѧϰ LINQ — LINQ ڲѯԼ XML DOM ʱʵáʹõȻϾɵĻ XmlDocument DOMLINQ to XML DOM һ־ϷЧĽ

о SQL LINQ дIJѯʹ LINQ SQL ø濢

LINQ ʵս

Щֻ LINQ ݿѯΪЧʡ

ӦóıдԣҵС˽Ҿһʹ LINQ ݻ㣨ʹһ LINQ SQL Entity Framework APIԽݻֲֿʱ俳һ룬ҿάԽɡ

ԭĵַhttps://www.linqpad.net/WhyLINQBeatsSQL.aspx