2016-03-07 16 views
21

Ben LinqPad sorguları ile deneyler oldum. Ben sql sorgusu Lots.Where(l => l.Side == 'A') bir linq yazarken bir sütun Side char(1) ile masa Lot., o Lots.Where(l => l.Side.Equals('A')) kullanarak,Farklı SQL nereden üretildi (l => l.Side == 'A') vs Nerede (l => l.Side.Equals ('A')

-- Region Parameters 
DECLARE @p0 Int = 65 
-- EndRegion 
SELECT ..., [t0].[Side], ... 
FROM [Lot] AS [t0] 
WHERE UNICODE([t0].[Side]) = @p0 

Ancak aşağıdaki sQL üretir, bu naif de olsa (

-- Region Parameters 
DECLARE @p0 Char(1) = 'A' 
-- EndRegion 
SELECT ..., [t0].[Side], ... 
FROM [Lot] AS [t0] 
WHERE [t0].[Side] = @p0 

o üzerine oluşacak üretir) Denetim, o ikinci marjinal olarak daha hızlı olurdu, çünkü UNICODE numaralı aramaya gerek duymuyor.

int, smallint veya == veya .Equals üretilen SQL arasında hiçbir fark yoktur varchar sütunları, neden char(1) edilir kullanma ve ilgili C# tipi char farklı?

Belirli bir sütun türünün iki eşitlik denetimi biçimiyle farklı SQL üretip üretmeyeceğini tahmin etmenin bir yolu var mı?

Düzenleme:

MS SQL tarafından desteklenen her türlü kontrol ettik ve sadece char(1) ve nchar(1) bu davranışı gösterirler. Her ikisi de System.Char türüyle LinqToSql'de temsil edilir. o kasıtlı bir karar olsaydı, o zaman System.Byte ile temsil (ancak bunun yerine 1 uzunluğunda System.Linq.Binary olduğunu olabilir binary(1) aynı davranışı, umuyordum

Düzenleme 2:. alakalı olması durumunda, öyleyim LINQPad kullanarak yaratılan SQL'i görüntülemekteyim Linqpad'in sistemin LinqToSQL'i kullanacağını varsayıyordum, ama bugün bu varsayımın kusurlu olabileceğini düşünüyordum.

Düzenleme 3: LinqToSQL sistemini test etmek için hızlı bir VS projesi yürüttüm ve aynı sonucu elde edin:

Kod:

static void Main(string[] args) 
{ 
    var db = new DataClasses1DataContext {Log = Console.Out}; 
    Console.Out.WriteLine("l.Side == 'A'"); 
    Console.Out.WriteLine("============="); 
    Console.Out.WriteLine(); 
    foreach (Lot ll in db.Lots.Where(l => l.Side == 'A')) 
    { 
     break; 
    } 
    Console.Out.WriteLine(); 
    Console.Out.WriteLine("---------------------------------------"); 
    Console.Out.WriteLine(); 

    Console.Out.WriteLine("l.Side.Equals('A')"); 
    Console.Out.WriteLine("=================="); 
    Console.Out.WriteLine(); 
    foreach (Lot ll in db.Lots.Where(l => l.Side.Equals('A'))) 
    { 
     break; 
    } 
    Console.In.Read(); 
} 

Çıktı:

l.Side == 'A' 
============= 

SELECT ..., [t0].[Side], ... 
FROM [dbo].[Lot] AS [t0] 
WHERE UNICODE([t0].[Side]) = @p0 
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [65] 
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.6.1532.0 


--------------------------------------- 

l.Side.Equals('A') 
================== 

SELECT ..., [t0].[Side], ... 
FROM [dbo].[Lot] AS [t0] 
WHERE [t0].[Side] = @p0 
-- @p0: Input Char (Size = 1; Prec = 0; Scale = 0) [A] 
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.6.1532.0 

O .Equals versiyonunda, bu char olarak geçirilen oysa == 'A' versiyonunda, parametre, bir int olarak geçirilen olduğunu ilginçtir.

The dbml and table creation script are in this gist.

+0

DBML eşleştirmesini yayınlayabilir misiniz? – usr

+0

@usr, bu LINQPad aracılığıyla oldu, bunun için haritalamayı nasıl alacağımı bilmiyorum. – RoadieRich

cevap

12

bu konuda bazı documentation vardır: SQL Server

Uyuşmazlıkları: Sabit uzunluk karakteri türleri. Transact-SQL Unicode ve Unicode olmayan kategoriler arasında ayrım yapar ve her kategoride üç farklı türü vardır: sabit uzunluk nchar/char, değişken uzunluk nvarchar/varchar ve büyük boyutlu ntext/text. Sabit uzunluk karakter türleri CLR System.Char türüne karakterleri bulmak için eşleştirilebilir, ancak gerçekten aynı türde dönüşümlere ve davranışlara karşılık gelmez.

Ve L2S kaynak kodu değişmez dize "UNICODE" kullanan tek bir yere sahiptir:

enter image description here

O göstermek işlevi için gerekli bir önkoşul olan SqlUnary sözdizimi ağacı düğümü olduğu görülüyor tip Convert:

enter image description here

bilmiyorum IsNumeric koşulunu nasıl karşılamayı başardınız. Orada bir tür uyumsuzluğun olduğunu düşünüyorum. Sütun gerçekten System.Char olarak mı eşlenmiş?

Muhtemelen Equals çağrı, bu kod yolunu tetiklemiyor. Bu muhtemelen bir L2S hatasıdır. Kaynak kodunda birden çok yere tercüme edilir. İşte bunlardan biri: bu Herhangi bir bağımsız değişken dönüşümleri atlar gibi

enter image description here

görünüyor. Tartışmanın ne olduğu umurumda değil. Bu muhtemelen çeşitli sorgular ile başarısız olur (bu muhtemelen bir hata). l.Side.Equals(1.2m) yazarsanız ne olur merak ediyorum. Bu tam anlamıyla SQL'e çevirir sanırım.


Şimdi yeniden ürettim. Sütunu string ile eşleştirin. Bu oluşturulan SQL'i düzeltir. Yürütme planı, oluşturulmakta olan SQL ile bir dizin aramasının mümkün olduğunu gösterir.

+0

'l.Side.Equals (1.2m)' bir 'InvalidCastException '(' System.Decimal 'türünden' System.Char 'türüne dönüştürülemedi.) Herhangi bir SQL üretilmeden önce - en azından, görünür sql olmadan içsel olarak kazma. – RoadieRich

+0

Büyük olasılıkla herhangi bir fark yaratırsa, oluşturulan SQL'i görüntülemek için LINQPad kullanıyorum eklemeliyim. LINQPad'ın sistem L2S kütüphanesini kullanacağını varsayıyordum, ama varsayımın kusurlu olduğunu fark ettim. – RoadieRich

+0

LinqPad, muhtemelen değiştirilmemiş ikili dosyaları kullanır. Eşlemeyi L2S'nin çalışma zamanı meta veri sistemi üzerinden sorgulayabilirsiniz. Bunun için MSDN belgeleri var. Ancak testlerinizi yürütmek için bir VS projesi oluşturduysanız daha iyi olurdu. Şu anda, LinqPad'in her türlü garip eşleştirmeyi ve invaziv teknikleri kullanabilmesi için nasıl bir yol izleyeceğimi bilmiyorum. – usr

İlgili konular