0

Basitleştirilmiş örnek: FirstName, LastName ile bir tablom var. Tam selamlama uzunluğuna göre N uzunluğuna sahip olmayan tüm insanları almakla ilgileniyorum. Bunu başarmak için, bu gibi bir kod vardır:Entity Framework'de bir projeksiyon seçin ve filtrele

var result = await Context.People 
       .Select(p => new PersonWithSalutation 
       { 
        FirstName = p.FirstName, 
        LastName = p.FirstName, 
        FullSalutation = p.FirstName + " " + p.LastName 
       }) 
       .Where(p => p.FullSalutation.Length < maxLength) 
       .OrderBy(p => p.FullSalutation) 
       .Take(maxResults) 
       .ToListAsync(); 

sorgu şuna benzer:

SELECT TOP (10) 
    [Project1].[C1] AS [C1], 
    [Project1].[Name] AS [Name], 
    [Project1].[Id] AS [Id], 
    [Project1].[C2] AS [C2] 
    FROM (SELECT 
     [Extent1].[Id] AS [Id], 
     [Extent1].[Name] AS [Name], 
     1 AS [C1], 
     ...calculated stuff... AS [C2] 
     FROM [dbo].[People] AS [Extent1] 
     WHERE ...exactly the same stuff... <= @p__linq__3 
    ) AS [Project1] 
    ORDER BY [Project1].[C2] ASC 

Bu hile yapar ve veritabanına tek bir sorgu oluşturur. Sorun, ortaya çıkan sorguda iki kez göründüğünden hesaplanan yansıtmadır: bir kez SELECT ve daha sonra bir WHERE maddesinde. Bu örnek basitleştirilmiştir, ancak gerçek durumumda, sadece bir kez hesaplanmayı tercih edeceğim ağır matematiksel işlemleri yapıyorum. Yukarıda gördüğünüz gibi, C2 sipariş maddesinde yeniden kullanılır. Aynı şeyi, başka bir alt soruyu içereceğini düşündüğüm WHERE yan tümcesiyle yapmak istiyorum). Bunu nasıl başarabilirim?

+0

yapmam hesaplama aynı olduğunu fark değil SQL Server düsünebilirdi Bu durumda iki kez. Buna inanmak için bir nedeniniz var mı? – John

cevap

1

Sorgudaki bina çok belirsiz bir işlem olduğundan, istediğiniz linq aramasını yaparak çok fazla zaman harcayabilirsiniz. Bu yüzden başka bir yaklaşım öneririm. POCO sınıfınıza FullSalutation mülkünü ekleyin ve FirstName veya LastName değiştiğinde DB yoluyla hesaplanacaktır (Computed). Bu durumda, gerçekten gerekli, tekrarlar olmadan, istediğiniz gibi hesaplamalar yapılacaktır.

public class POCO 
{ 
    public int ID { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)] 
    public string FullSalutation { get; private set; } 
} 

Ardından yeni göç ekleyin:

public override void Up() 
{ 
    //AddColumn("dbo.People", "FullSalutation", x => x.String()); 
    Sql("ALTER TABLE dbo.People ADD FullSalutation AS FirstName + ' ' + LastName"); 
} 
public override void Down() 
{ 
    DropColumn("dbo.People", "FullSalutation"); 
} 

Son olarak, sorgu aşağıdaki gibi görünecektir:

var result = await Context.People 
      .Where(p => p.FullSalutation.Length < maxLength) 
      .Select(p => new PersonWithSalutation 
      { 
        FirstName = p.FirstName, 
        LastName = p.LastName, 
        FullSalutation = p.FullSalutation 
      }).OrderBy(p => p.FullSalutation).Take(maxResults).ToListAsync();