2013-11-20 21 views
6

Tôi có truy vấn LINQ nàyTại sao Entity Framework 6 tạo các truy vấn SQL phức tạp cho tra cứu đơn giản?

dbContext.Customers.Where(c => c.AssetTag == assetTag).Count(); 

hoặc

(from c in dbContext.Customers 
where c.AssetTag == assetTag 
select c).Count(); 

SQL được tạo ra là

SELECT 
[GroupBy1].[A1] AS [C1] 
FROM (SELECT 
    COUNT(1) AS [A1] 
    FROM [dbo].[Customer] AS [Extent1] 
    WHERE (([Extent1].[AssetTag] = @p__linq__0) AND (NOT ([Extent1].[AssetTag] IS NULL OR @p__linq__0 IS NULL))) OR (([Extent1].[AssetTag] IS NULL) AND (@p__linq__0 IS NULL)) 
) AS [GroupBy1] 

Vậy tại sao LINQ tạo SQL phức tạp như vậy cho một nơi tuyên bố đơn giản?

+2

Cột '[AssetTag]' của bạn có được phép là 'null' không ?. –

+1

dường như không phức tạp với tôi, nó chỉ tạo ra một tuyên bố để bảo vệ cuộc gọi của bạn từ một mức độ không. – Claies

+0

bạn có thể cho tôi biết làm thế nào bạn có thể nhận được các truy vấn SQL này từ Linq hay Lamda .. điều này không liên quan đến câu hỏi của bạn Tôi đang gặp khó khăn. –

Trả lời

7

trong tương đương chuỗi C#, null == null đánh giá là True. null == null trong cơ sở dữ liệu đánh giá là False. Kịch bản lệnh xác minh rằng cả giá trị cột và tham số là null hoặc cả hai đều không có giá trị rỗng và chúng có cùng giá trị chuỗi.

WHERE 
    (
     -- neither the column nor the paramter are null and 
     -- the column and the parameter have the same string value 
     ([Extent1].[AssetTag] = @p__linq__0) AND 
     (NOT ([Extent1].[AssetTag] IS NULL OR @p__linq__0 IS NULL)) 
    ) 
    OR 
    (
     -- both the column value and the parameter are null 
     ([Extent1].[AssetTag] IS NULL) AND 
     (@p__linq__0 IS NULL) 
    ) 
+0

Cảm ơn Mọi người vì lời giải thích –

6

Đó WHERE điều kiện được tạo ra theo cách này bởi vì với thiết lập NULLS ANSI, so sánh AssetTag == null sẽ không trả lại hàng tương ứng trong SQL (vì trong SQL thế giới khi so sánh vô null kết quả là null). Để giữ cho hành vi truy vấn giống như một nhà phát triển C# mong đợi, EF tạo ra mệnh đề WHERE mở rộng. Lưu ý rằng các phiên bản trước của EF không làm như vậy và do đó không hoạt động trên cơ sở dữ liệu với cài đặt ANSI NULLS. Các dự án GroupBy là có bởi vì EF hỗ trợ nhiều truy vấn phức tạp hơn trước cuộc gọi .Count(), chẳng hạn như join, projections vv Cách tiếp cận này do đó chung chung hơn vì nó cũng sẽ làm việc với tất cả các kịch bản đó.

+0

Tôi sẽ cố gắng giải thích mức độ, nhưng không biết cách giải thích nó mặc dù có một sự hiểu biết hời hợt về nó. 1 cho đặt nó rất thanh lịch. – AaronLS

+0

+1 để đề cập rằng EF trước 6 không * không * làm điều này. – CrazyPyro

5

Đối với một điều, trong C# c.AssetTag == assetTag sẽ là đúng nếu cả hai đều là rỗng. Trong SQL tuy nhiên, null so với bất cứ điều gì luôn luôn là sai. Do đó, nếu chúng ta muốn tạo ra một truy vấn mà sau C# so sánh cơ, chúng ta phải thêm điều kiện bổ sung để đảm bảo vô rồi so sánh để đánh giá đúng nếu cả hai đều null:

([Extent1].[AssetTag] IS NULL) AND (@p__linq__0 IS NULL)

8

Trong EF6 cơ sở dữ liệu ngữ nghĩa null ngữ nghĩa so sánh mặc định. Lưu ý rằng đây là thay đổi đối với cài đặt mặc định trong EF5. Trong EF5 lá cờ này được chôn cất trong ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior và theo mặc định EF sẽ sử dụng LINQ to ngữ nghĩa so sánh đối tượng. Trong EF6, nó được hiển thị trên DbContext dưới dạng DbContext.Configuration.UseDatabaseNullSemantics. Bạn có thể tìm thêm chi tiết here

+2

Trang trợ giúp msdn được liên kết của bạn cho biết giá trị mặc định của 'DbContextConfiguration.UseDatabaseNullSemantics' là sai - vì vậy trong ngữ nghĩa null của cơ sở dữ liệu EF6 KHÔNG phải là ngữ nghĩa so sánh mặc định? – springy76

Các vấn đề liên quan