2015-05-12 2 views
8

ho questo semplice modello su un nuovo progetto fresco:Extra unisce il molto semplice query EF per 1-1 rapporto

class A 
{ 
    public int Id { get; set; } 
    public B B { get; set; } 
} 

class B 
{ 
    public int Id { get; set; } 
    public string Text { get; set; } 
} 

class C 
{ 
    public int Id { get; set; } 
    public B B { get; set; } 
} 

Le mappature sono:

modelBuilder.Entity<A>().HasOptional(x => x.B).WithOptionalDependent(); 
modelBuilder.Entity<C>().HasOptional(x => x.B).WithOptionalDependent(); 

Sto facendo funzionare questa domanda:

db.As.Include(a => a.B).Where(a => a.B.Text == "10").FirstOrDefault(); 

Dove db.As è la DbSet di A di.

Esso genera il seguente SQL

SELECT TOP (1) 
    [Extent1].[Id] AS [Id], 
    [Join8].[Id1] AS [Id1], 
    [Join8].[Text] AS [Text], 
    [Join11].[Id2] AS [Id2], 
    [Join14].[Id3] AS [Id3] 
    FROM  [dbo].[A] AS [Extent1] 
    INNER JOIN (SELECT [Extent2].[Text] AS [Text], [Extent3].[Id] AS [Id4] 
     FROM [dbo].[B] AS [Extent2] 
     LEFT OUTER JOIN [dbo].[A] AS [Extent3] ON ([Extent3].[B_Id] IS NOT NULL) AND ([Extent2].[Id] = [Extent3].[B_Id]) 
     LEFT OUTER JOIN [dbo].[C] AS [Extent4] ON ([Extent4].[B_Id] IS NOT NULL) AND ([Extent2].[Id] = [Extent4].[B_Id])) AS [Join2] ON [Extent1].[Id] = [Join2].[Id4] 
    INNER JOIN (SELECT [Extent5].[Text] AS [Text], [Extent6].[Id] AS [Id5] 
     FROM [dbo].[B] AS [Extent5] 
     LEFT OUTER JOIN [dbo].[A] AS [Extent6] ON ([Extent6].[B_Id] IS NOT NULL) AND ([Extent5].[Id] = [Extent6].[B_Id]) 
     LEFT OUTER JOIN [dbo].[C] AS [Extent7] ON ([Extent7].[B_Id] IS NOT NULL) AND ([Extent5].[Id] = [Extent7].[B_Id])) AS [Join5] ON [Extent1].[Id] = [Join5].[Id5] 
    LEFT OUTER JOIN (SELECT [Extent8].[Id] AS [Id1], [Extent8].[Text] AS [Text], [Extent9].[Id] AS [Id6] 
     FROM [dbo].[B] AS [Extent8] 
     LEFT OUTER JOIN [dbo].[A] AS [Extent9] ON ([Extent9].[B_Id] IS NOT NULL) AND ([Extent8].[Id] = [Extent9].[B_Id]) 
     LEFT OUTER JOIN [dbo].[C] AS [Extent10] ON ([Extent10].[B_Id] IS NOT NULL) AND ([Extent8].[Id] = [Extent10].[B_Id])) AS [Join8] ON [Extent1].[Id] = [Join8].[Id6] 
    LEFT OUTER JOIN (SELECT [Extent12].[Id] AS [Id2] 
     FROM [dbo].[B] AS [Extent11] 
     LEFT OUTER JOIN [dbo].[A] AS [Extent12] ON ([Extent12].[B_Id] IS NOT NULL) AND ([Extent11].[Id] = [Extent12].[B_Id]) 
     LEFT OUTER JOIN [dbo].[C] AS [Extent13] ON ([Extent13].[B_Id] IS NOT NULL) AND ([Extent11].[Id] = [Extent13].[B_Id])) AS [Join11] ON [Extent1].[Id] = [Join11].[Id2] 
    LEFT OUTER JOIN (SELECT [Extent15].[Id] AS [Id7], [Extent16].[Id] AS [Id3] 
     FROM [dbo].[B] AS [Extent14] 
     LEFT OUTER JOIN [dbo].[A] AS [Extent15] ON ([Extent15].[B_Id] IS NOT NULL) AND ([Extent14].[Id] = [Extent15].[B_Id]) 
     LEFT OUTER JOIN [dbo].[C] AS [Extent16] ON ([Extent16].[B_Id] IS NOT NULL) AND ([Extent14].[Id] = [Extent16].[B_Id])) AS [Join14] ON [Extent1].[Id] = [Join14].[Id7] 
    WHERE (N'10' = [Join2].[Text]) AND ([Join5].[Text] IS NOT NULL) 

che sembra complicato per me. Si "unisce" anche a C che non faccio riferimento ad A né B e non è incluso nella query.

Ora, il fatto è: abbiamo un grande progetto con alcuni modelli molto complessi, stiamo riscontrando alcuni problemi di prestazioni, quando abbiamo profilato le query abbiamo scoperto che c'erano query che dovevano "includere" un sacco di entità e hanno generato SQL di oltre 3k linee.

C'è qualcosa di sbagliato nelle nostre mappature o nella nostra configurazione? Abbiamo il caricamento lazy e la creazione del proxy disabilitata.

+0

Quale versione di Entity Framework sono in esecuzione? – Jorriss

+0

Sto utilizzando Entity Framework 6.0.2 –

risposta

3

Non ho una risposta reale per te, ma con le stesse specifiche avrei writen:

modelBuilder.Entity<A>().HasOptional(x => x.B).WithMany(); 
modelBuilder.Entity<C>().HasOptional(x => x.B).WithMany(); 

che dà lo stesso schema del database come la tua.

Perché dovrei averlo fatto: perché spesso penso in termini di "quale schema voglio?", E con la mia pratica, per questo schema, il codice è quello sopra.

BTW: risultante query per ctx.Set<A>().Include(x => x.B).Where(x => x.B.Text == "10").Select(x => x) è:

SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent3].[Id] AS [Id1], 
    [Extent3].[Text] AS [Text] 
FROM 
    [dbo].[A] AS [Extent1] 
    INNER JOIN [dbo].[B] AS [Extent2] ON [Extent1].[B_Id] = [Extent2].[Id] 
    LEFT OUTER JOIN [dbo].[B] AS [Extent3] ON [Extent1].[B_Id] = [Extent3].[Id] 
WHERE 
    N'10' = [Extent2].[Text] 

ma ancora qui: perché extend3?

Perché Extend2 permette di filtrare la A senza B: cioè inner join ... extend2 è una in cui (? Veramente chiaro, no)