Някои аспСкти Π½Π° оптимизацията Π½Π° LINQ заявки Π² C#.NET Π·Π° MS SQL Server

LINQ Π½Π°Π²Π»Π΅Π·Π΅ Π² .NET ΠΊΠ°Ρ‚ΠΎ ΠΌΠΎΡ‰Π΅Π½ Π½ΠΎΠ² Π΅Π·ΠΈΠΊ Π·Π° ΠΌΠ°Π½ΠΈΠΏΡƒΠ»ΠΈΡ€Π°Π½Π΅ Π½Π° Π΄Π°Π½Π½ΠΈ. LINQ to SQL ΠΊΠ°Ρ‚ΠΎ част ΠΎΡ‚ Π½Π΅Π³ΠΎ Π²ΠΈ позволява Π΄Π° ΠΊΠΎΠΌΡƒΠ½ΠΈΠΊΠΈΡ€Π°Ρ‚Π΅ със Π‘Π£Π‘Π” доста ΡƒΠ΄ΠΎΠ±Π½ΠΎ, ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Entity Framework. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ Π³ΠΎ доста чСсто, Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΡ†ΠΈΡ‚Π΅ забравят Π΄Π° ΠΏΠΎΠ³Π»Π΅Π΄Π½Π°Ρ‚ какъв Π²ΠΈΠ΄ SQL заявка Ρ‰Π΅ Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° Π΄ΠΎΡΡ‚Π°Π²Ρ‡ΠΈΠΊΡŠΡ‚, ΠΊΠΎΠΉΡ‚ΠΎ ΠΏΠΎΠ΄Π»Π΅ΠΆΠΈ Π½Π° Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅, във вашия случай, Entity Framework.

НСка Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ Π΄Π²Π΅ основни Ρ‚ΠΎΡ‡ΠΊΠΈ с ΠΏΡ€ΠΈΠΌΠ΅Ρ€.
Π—Π° Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ Ρ‚ΠΎΠ²Π°, Π² SQL Server Ρ‰Π΅ създадСм Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ Test ΠΈ Π² нСя Ρ‰Π΅ създадСм Π΄Π²Π΅ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ слСдната заявка:

БъздаванС Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ

USE [TEST]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Ref](
	[ID] [int] NOT NULL,
	[ID2] [int] NOT NULL,
	[Name] [nvarchar](255) NOT NULL,
	[InsertUTCDate] [datetime] NOT NULL,
 CONSTRAINT [PK_Ref] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Ref] ADD  CONSTRAINT [DF_Ref_InsertUTCDate]  DEFAULT (getutcdate()) FOR [InsertUTCDate]
GO

USE [TEST]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Customer](
	[ID] [int] NOT NULL,
	[Name] [nvarchar](255) NOT NULL,
	[Ref_ID] [int] NOT NULL,
	[InsertUTCDate] [datetime] NOT NULL,
	[Ref_ID2] [int] NOT NULL,
 CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Customer] ADD  CONSTRAINT [DF_Customer_Ref_ID]  DEFAULT ((0)) FOR [Ref_ID]
GO

ALTER TABLE [dbo].[Customer] ADD  CONSTRAINT [DF_Customer_InsertUTCDate]  DEFAULT (getutcdate()) FOR [InsertUTCDate]
GO

Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° попълним Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° Ref, ΠΊΠ°Ρ‚ΠΎ изпълним слСдния скрипт:

ПопълванС Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° Π Π΅Ρ„

USE [TEST]
GO

DECLARE @ind INT=1;

WHILE(@ind<1200000)
BEGIN
	INSERT INTO [dbo].[Ref]
           ([ID]
           ,[ID2]
           ,[Name])
    SELECT
           @ind
           ,@ind
           ,CAST(@ind AS NVARCHAR(255));

	SET @ind=@ind+1;
END 
GO

НСка попълним Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° Customer ΠΏΠΎ ΡΡŠΡ‰ΠΈΡ Π½Π°Ρ‡ΠΈΠ½, ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ слСдния скрипт:

ПопълванС Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° ΠšΠ»ΠΈΠ΅Π½Ρ‚

USE [TEST]
GO

DECLARE @ind INT=1;
DECLARE @ind_ref INT=1;

WHILE(@ind<=12000000)
BEGIN
	IF(@ind%3=0) SET @ind_ref=1;
	ELSE IF (@ind%5=0) SET @ind_ref=2;
	ELSE IF (@ind%7=0) SET @ind_ref=3;
	ELSE IF (@ind%11=0) SET @ind_ref=4;
	ELSE IF (@ind%13=0) SET @ind_ref=5;
	ELSE IF (@ind%17=0) SET @ind_ref=6;
	ELSE IF (@ind%19=0) SET @ind_ref=7;
	ELSE IF (@ind%23=0) SET @ind_ref=8;
	ELSE IF (@ind%29=0) SET @ind_ref=9;
	ELSE IF (@ind%31=0) SET @ind_ref=10;
	ELSE IF (@ind%37=0) SET @ind_ref=11;
	ELSE SET @ind_ref=@ind%1190000;
	
	INSERT INTO [dbo].[Customer]
	           ([ID]
	           ,[Name]
	           ,[Ref_ID]
	           ,[Ref_ID2])
	     SELECT
	           @ind,
	           CAST(@ind AS NVARCHAR(255)),
	           @ind_ref,
	           @ind_ref;


	SET @ind=@ind+1;
END
GO

Π’Π°ΠΊΠ° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ…ΠΌΠ΅ Π΄Π²Π΅ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ, Π΅Π΄Π½Π°Ρ‚Π° ΠΎΡ‚ ΠΊΠΎΠΈΡ‚ΠΎ ΠΈΠΌΠ° ΠΏΠΎΠ²Π΅Ρ‡Π΅ ΠΎΡ‚ 1 ΠΌΠΈΠ»ΠΈΠΎΠ½ Ρ€Π΅Π΄Π° с Π΄Π°Π½Π½ΠΈ, Π° Π΄Ρ€ΡƒΠ³Π°Ρ‚Π° ΠΈΠΌΠ° ΠΏΠΎΠ²Π΅Ρ‡Π΅ ΠΎΡ‚ 10 ΠΌΠΈΠ»ΠΈΠΎΠ½Π° Ρ€Π΅Π΄Π° с Π΄Π°Π½Π½ΠΈ.

Π‘Π΅Π³Π° във Visual Studio трябва Π΄Π° ΡΡŠΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ тСстов ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ Π·Π° ΠΊΠΎΠ½Π·ΠΎΠ»Π½ΠΎ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π½Π° Visual C# (.NET Framework):

Някои аспСкти Π½Π° оптимизацията Π½Π° LINQ заявки Π² C#.NET Π·Π° MS SQL Server

Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° трябва Π΄Π° Π΄ΠΎΠ±Π°Π²ΠΈΡ‚Π΅ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π° Entity Framework, Π·Π° Π΄Π° взаимодСйства с Π±Π°Π·Π°Ρ‚Π° Π΄Π°Π½Π½ΠΈ.
Π—Π° Π΄Π° Π³ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚Π΅, Ρ‰Ρ€Π°ΠΊΠ½Π΅Ρ‚Π΅ с дСсния Π±ΡƒΡ‚ΠΎΠ½ Π²ΡŠΡ€Ρ…Ρƒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ΠΈ ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ NuGet ΠΎΡ‚ контСкстното мСню:

Някои аспСкти Π½Π° оптимизацията Π½Π° LINQ заявки Π² C#.NET Π·Π° MS SQL Server

Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° Π² ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†Π° Π·Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ NuGet, ΠΊΠΎΠΉΡ‚ΠΎ сС ΠΏΠΎΠΊΠ°Π·Π²Π°, Π² ΠΏΠΎΠ»Π΅Ρ‚ΠΎ Π·Π° Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅ Π²ΡŠΠ²Π΅Π΄Π΅Ρ‚Π΅ Π΄ΡƒΠΌΠ°Ρ‚Π° β€žEntity Frameworkβ€œ ΠΈ ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Π° Entity Framework ΠΈ Π³ΠΎ инсталирайтС:

Някои аспСкти Π½Π° оптимизацията Π½Π° LINQ заявки Π² C#.NET Π·Π° MS SQL Server

Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° във Ρ„Π°ΠΉΠ»Π° App.config, слСд ΠΊΠ°Ρ‚ΠΎ Π·Π°Ρ‚Π²ΠΎΡ€ΠΈΡ‚Π΅ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚Π° configSections, Π΄ΠΎΠ±Π°Π²Π΅Ρ‚Π΅ слСдния Π±Π»ΠΎΠΊ:

<connectionStrings>
    <add name="DBConnection" connectionString="data source=ИМЯ_Π­ΠšΠ—Π•ΠœΠŸΠ›Π―Π Π_MSSQL;Initial Catalog=TEST;Integrated Security=True;" providerName="System.Data.SqlClient" />
</connectionStrings>

Π’ connectionString трябва Π΄Π° Π²ΡŠΠ²Π΅Π΄Π΅Ρ‚Π΅ Π½ΠΈΠ·Π° Π·Π° Π²Ρ€ΡŠΠ·ΠΊΠ°.

Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° създадСм 3 интСрфСйса Π² ΠΎΡ‚Π΄Π΅Π»Π½ΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅:

  1. ВнСдряванС Π½Π° интСрфСйса IBaseEntityID
    namespace TestLINQ
    {
        public interface IBaseEntityID
        {
            int ID { get; set; }
        }
    }
    

  2. ВнСдряванС Π½Π° интСрфСйса IBaseEntityName
    namespace TestLINQ
    {
        public interface IBaseEntityName
        {
            string Name { get; set; }
        }
    }
    

  3. ВнСдряванС Π½Π° интСрфСйса IBaseNameInsertUTCDate
    namespace TestLINQ
    {
        public interface IBaseNameInsertUTCDate
        {
            DateTime InsertUTCDate { get; set; }
        }
    }
    

И Π² ΠΎΡ‚Π΄Π΅Π»Π΅Π½ Ρ„Π°ΠΉΠ» Ρ‰Π΅ създадСм Π±Π°Π·ΠΎΠ² клас BaseEntity Π·Π° Π½Π°ΡˆΠΈΡ‚Π΅ Π΄Π²Π° ΠΎΠ±Π΅ΠΊΡ‚Π°, ΠΊΠΎΠΉΡ‚ΠΎ Ρ‰Π΅ Π²ΠΊΠ»ΡŽΡ‡Π²Π° ΠΎΠ±Ρ‰ΠΈ ΠΏΠΎΠ»Π΅Ρ‚Π°:

РСализация Π½Π° базовия клас BaseEntity

namespace TestLINQ
{
    public class BaseEntity : IBaseEntityID, IBaseEntityName, IBaseNameInsertUTCDate
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public DateTime InsertUTCDate { get; set; }
    }
}

Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° Π² ΠΎΡ‚Π΄Π΅Π»Π½ΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Ρ‰Π΅ създадСм Π½Π°ΡˆΠΈΡ‚Π΅ Π΄Π²Π° ΠΎΠ±Π΅ΠΊΡ‚Π°:

  1. РСализация Π½Π° Ρ€Π΅Ρ„Π΅Ρ€Π΅Π½Ρ‚Π΅Π½ клас
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace TestLINQ
    {
        [Table("Ref")]
        public class Ref : BaseEntity
        {
            public int ID2 { get; set; }
        }
    }
    

  2. РСализация Π½Π° клас ΠšΠ»ΠΈΠ΅Π½Ρ‚
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace TestLINQ
    {
        [Table("Customer")]
        public class Customer: BaseEntity
        {
            public int Ref_ID { get; set; }
            public int Ref_ID2 { get; set; }
        }
    }
    

Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° създадСм контСкст Π½Π° UserContext Π² ΠΎΡ‚Π΄Π΅Π»Π΅Π½ Ρ„Π°ΠΉΠ»:

РСализация Π½Π° класа UserContex

using System.Data.Entity;

namespace TestLINQ
{
    public class UserContext : DbContext
    {
        public UserContext()
            : base("DbConnection")
        {
            Database.SetInitializer<UserContext>(null);
        }

        public DbSet<Customer> Customer { get; set; }
        public DbSet<Ref> Ref { get; set; }
    }
}

ΠŸΠΎΠ»ΡƒΡ‡ΠΈΡ…ΠΌΠ΅ Π³ΠΎΡ‚ΠΎΠ²ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π·Π° ΠΏΡ€ΠΎΠ²Π΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΎΠ½Π½ΠΈ тСстовС с LINQ to SQL ΠΏΡ€Π΅Π· EF Π·Π° MS SQL Server:

Някои аспСкти Π½Π° оптимизацията Π½Π° LINQ заявки Π² C#.NET Π·Π° MS SQL Server

Π‘Π΅Π³Π° във Ρ„Π°ΠΉΠ»Π° Program.cs Π²ΡŠΠ²Π΅Π΄Π΅Ρ‚Π΅ слСдния ΠΊΠΎΠ΄:

Π€Π°ΠΉΠ» Program.cs

using System;
using System.Collections.Generic;
using System.Linq;

namespace TestLINQ
{
    class Program
    {
        static void Main(string[] args)
        {
            using (UserContext db = new UserContext())
            {
                var dblog = new List<string>();
                db.Database.Log = dblog.Add;

                var query = from e1 in db.Customer
                            from e2 in db.Ref
                            where (e1.Ref_ID == e2.ID)
                                 && (e1.Ref_ID2 == e2.ID2)
                            select new { Data1 = e1.Name, Data2 = e2.Name };

                var result = query.Take(1000).ToList();

                Console.WriteLine(dblog[1]);

                Console.ReadKey();
            }
        }
    }
}

Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° Π½Π΅ΠΊΠ° изпълним нашия ΠΏΡ€ΠΎΠ΅ΠΊΡ‚.

Π’ края Π½Π° Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚Π° Π½Π° ΠΊΠΎΠ½Π·ΠΎΠ»Π°Ρ‚Π° Ρ‰Π΅ сС ΠΏΠΎΠΊΠ°ΠΆΠ΅ слСдното:

Π“Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π° SQL заявка

SELECT TOP (1000) 
    [Extent1].[Ref_ID] AS [Ref_ID], 
    [Extent1].[Name] AS [Name], 
    [Extent2].[Name] AS [Name1]
    FROM  [dbo].[Customer] AS [Extent1]
    INNER JOIN [dbo].[Ref] AS [Extent2] ON ([Extent1].[Ref_ID] = [Extent2].[ID]) AND ([Extent1].[Ref_ID2] = [Extent2].[ID2])

Π’ΠΎΠ²Π° ΠΎΠ·Π½Π°Ρ‡Π°Π²Π°, Ρ‡Π΅ ΠΊΠ°Ρ‚ΠΎ цяло LINQ заявката Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° доста Π΄ΠΎΠ±Ρ€Π΅ SQL заявка към Π‘Π£Π‘Π” Π½Π° MS SQL Server.

Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈΠΌ условиСто И Π½Π° Π˜Π›Π˜ Π² LINQ заявката:

LINQ заявка

var query = from e1 in db.Customer
                            from e2 in db.Ref
                            where (e1.Ref_ID == e2.ID)
                                || (e1.Ref_ID2 == e2.ID2)
                            select new { Data1 = e1.Name, Data2 = e2.Name };

НСка стартирамС Π½Π°ΡˆΠ΅Ρ‚ΠΎ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΎΡ‚Π½ΠΎΠ²ΠΎ.

Π˜Π·ΠΏΡŠΠ»Π½Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Ρ‰Π΅ сС сринС с Π³Ρ€Π΅ΡˆΠΊΠ°, ΡΠ²ΡŠΡ€Π·Π°Π½Π° с Π²Ρ€Π΅ΠΌΠ΅Ρ‚ΠΎ Π·Π° изпълнСниС Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π°, Π½Π°Π΄Π²ΠΈΡˆΠ°Π²Π°Ρ‰ΠΎ 30 сСкунди:

Някои аспСкти Π½Π° оптимизацията Π½Π° LINQ заявки Π² C#.NET Π·Π° MS SQL Server

Ако ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅Ρ‚Π΅ коя заявка Π΅ Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π° ΠΎΡ‚ LINQ:

Някои аспСкти Π½Π° оптимизацията Π½Π° LINQ заявки Π² C#.NET Π·Π° MS SQL Server
, Ρ‚ΠΎΠ³Π°Π²Π° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° сС ΡƒΠ²Π΅Ρ€ΠΈΡ‚Π΅, Ρ‡Π΅ ΠΈΠ·Π±ΠΎΡ€ΡŠΡ‚ става Ρ‡Ρ€Π΅Π· дСкартовия ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ Π½Π° Π΄Π²Π° Π½Π°Π±ΠΎΡ€Π° (Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ):

Π“Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π° SQL заявка

SELECT TOP (1000) 
    [Extent1].[Ref_ID] AS [Ref_ID], 
    [Extent1].[Name] AS [Name], 
    [Extent2].[Name] AS [Name1]
    FROM  [dbo].[Customer] AS [Extent1]
    CROSS JOIN [dbo].[Ref] AS [Extent2]
    WHERE [Extent1].[Ref_ID] = [Extent2].[ID] OR [Extent1].[Ref_ID2] = [Extent2].[ID2]

НСка ΠΏΡ€Π΅Π½Π°ΠΏΠΈΡˆΠ΅ΠΌ LINQ заявката Ρ‚Π°ΠΊΠ°:

ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€Π°Π½Π° LINQ заявка

var query = (from e1 in db.Customer
                   join e2 in db.Ref
                   on e1.Ref_ID equals e2.ID
                   select new { Data1 = e1.Name, Data2 = e2.Name }).Union(
                        from e1 in db.Customer
                        join e2 in db.Ref
                        on e1.Ref_ID2 equals e2.ID2
                        select new { Data1 = e1.Name, Data2 = e2.Name });

Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°ΠΌΠ΅ слСдната SQL заявка:

SQL заявка

SELECT 
    [Limit1].[C1] AS [C1], 
    [Limit1].[C2] AS [C2], 
    [Limit1].[C3] AS [C3]
    FROM ( SELECT DISTINCT TOP (1000) 
        [UnionAll1].[C1] AS [C1], 
        [UnionAll1].[Name] AS [C2], 
        [UnionAll1].[Name1] AS [C3]
        FROM  (SELECT 
            1 AS [C1], 
            [Extent1].[Name] AS [Name], 
            [Extent2].[Name] AS [Name1]
            FROM  [dbo].[Customer] AS [Extent1]
            INNER JOIN [dbo].[Ref] AS [Extent2] ON [Extent1].[Ref_ID] = [Extent2].[ID]
        UNION ALL
            SELECT 
            1 AS [C1], 
            [Extent3].[Name] AS [Name], 
            [Extent4].[Name] AS [Name1]
            FROM  [dbo].[Customer] AS [Extent3]
            INNER JOIN [dbo].[Ref] AS [Extent4] ON [Extent3].[Ref_ID2] = [Extent4].[ID2]) AS [UnionAll1]
    )  AS [Limit1]

Π£Π²ΠΈ, Π² LINQ заявкитС ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠΌΠ° само Π΅Π΄Π½ΠΎ условиС Π·Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅, слСдоватСлно Π΅ възмоТно Π΄Π° сС Π½Π°ΠΏΡ€Π°Π²ΠΈ Π΅ΠΊΠ²ΠΈΠ²Π°Π»Π΅Π½Ρ‚Π½Π° заявка Ρ‡Ρ€Π΅Π· Π΄Π²Π΅ заявки Π·Π° всяко условиС, послСдвано ΠΎΡ‚ тяхното обСдиняванС Ρ‡Ρ€Π΅Π· Union Π·Π° ΠΏΡ€Π΅ΠΌΠ°Ρ…Π²Π°Π½Π΅ Π½Π° Π΄ΡƒΠ±Π»ΠΈΠΊΠ°Ρ‚ΠΈΡ‚Π΅ ΠΌΠ΅ΠΆΠ΄Ρƒ Ρ€Π΅Π΄ΠΎΠ²Π΅Ρ‚Π΅.
Π”Π°, заявкитС ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ Π½Π΅Π΅ΠΊΠ²ΠΈΠ²Π°Π»Π΅Π½Ρ‚Π½ΠΈ, ΠΊΠ°Ρ‚ΠΎ сС ΠΈΠΌΠ° ΠΏΡ€Π΅Π΄Π²ΠΈΠ΄, Ρ‡Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ Π²ΡŠΡ€Π½Π°Ρ‚ΠΈ пълни Π΄ΡƒΠ±Π»ΠΈΡ€Π°Π½ΠΈ Ρ€Π΅Π΄ΠΎΠ²Π΅. Π’ рСалния ΠΆΠΈΠ²ΠΎΡ‚ ΠΎΠ±Π°Ρ‡Π΅ ΠΏΡŠΠ»Π½ΠΈΡ‚Π΅ Π΄ΡƒΠ±Π»ΠΈΡ€Π°Π½ΠΈ Π»ΠΈΠ½ΠΈΠΈ Π½Π΅ са Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈ ΠΈ Ρ‚Π΅ сС ΠΎΠΏΠΈΡ‚Π²Π°Ρ‚ Π΄Π° сС ΠΎΡ‚ΡŠΡ€Π²Π°Ρ‚ ΠΎΡ‚ тях.

Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° сравним ΠΏΠ»Π°Π½ΠΎΠ²Π΅Ρ‚Π΅ Π·Π° изпълнСниС Π½Π° Ρ‚Π΅Π·ΠΈ Π΄Π²Π΅ заявки:

  1. Π·Π° CROSS JOIN срСдното Π²Ρ€Π΅ΠΌΠ΅ Π·Π° изпълнСниС Π΅ 195 сСкунди:
    Някои аспСкти Π½Π° оптимизацията Π½Π° LINQ заявки Π² C#.NET Π·Π° MS SQL Server
  2. Π·Π° INNER JOIN-UNION срСдното Π²Ρ€Π΅ΠΌΠ΅ Π·Π° изпълнСниС Π΅ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ ΠΎΡ‚ 24 сСкунди:
    Някои аспСкти Π½Π° оптимизацията Π½Π° LINQ заявки Π² C#.NET Π·Π° MS SQL Server

ΠšΠ°ΠΊΡ‚ΠΎ сС Π²ΠΈΠΆΠ΄Π° ΠΎΡ‚ Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ΠΈΡ‚Π΅, Π·Π° Π΄Π²Π΅ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ с ΠΌΠΈΠ»ΠΈΠΎΠ½ΠΈ записи, ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€Π°Π½Π°Ρ‚Π° LINQ заявка Π΅ Π² ΠΏΡŠΡ‚ΠΈ ΠΏΠΎ-Π±ΡŠΡ€Π·Π° ΠΎΡ‚ Π½Π΅ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€Π°Π½Π°Ρ‚Π°.

Π—Π° Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π° с И Π² условията Π½Π° LINQ заявка ΠΎΡ‚ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π°:

LINQ заявка

var query = from e1 in db.Customer
                            from e2 in db.Ref
                            where (e1.Ref_ID == e2.ID)
                                 && (e1.Ref_ID2 == e2.ID2)
                            select new { Data1 = e1.Name, Data2 = e2.Name };

ΠΏΠΎΡ‡Ρ‚ΠΈ Π²ΠΈΠ½Π°Π³ΠΈ Ρ‰Π΅ сС Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° ΠΏΡ€Π°Π²ΠΈΠ»Π½Π° SQL заявка, която Ρ‰Π΅ сС изпълнява срСдно Π·Π° ΠΎΠΊΠΎΠ»ΠΎ 1 сСкунда:

Някои аспСкти Π½Π° оптимизацията Π½Π° LINQ заявки Π² C#.NET Π·Π° MS SQL Server
Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Π·Π° ΠΌΠ°Π½ΠΈΠΏΡƒΠ»Π°Ρ†ΠΈΠΈ Π½Π° LINQ to Objects вмСсто Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅ към ΠΈΠ·Π³Π»Π΅Π΄Π°:

LINQ заявка (ΠΏΡŠΡ€Π²Π° опция)

var query = from e1 in seq1
                            from e2 in seq2
                            where (e1.Key1==e2.Key1)
                               && (e1.Key2==e2.Key2)
                            select new { Data1 = e1.Data, Data2 = e2.Data };

ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ заявка ΠΊΠ°Ρ‚ΠΎ:

LINQ заявка (ΠΏΡŠΡ€Π²Π° опция)

var query = from e1 in seq1
                            join e2 in seq2
                            on new { e1.Key1, e1.Key2 } equals new { e2.Key1, e2.Key2 }
                            select new { Data1 = e1.Data, Data2 = e2.Data };

ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ:

Π”Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½Π΅ Π½Π° Π΄Π²Π° масива

Para[] seq1 = new[] { new Para { Key1 = 1, Key2 = 2, Data = "777" }, new Para { Key1 = 2, Key2 = 3, Data = "888" }, new Para { Key1 = 3, Key2 = 4, Data = "999" } };
Para[] seq2 = new[] { new Para { Key1 = 1, Key2 = 2, Data = "777" }, new Para { Key1 = 2, Key2 = 3, Data = "888" }, new Para { Key1 = 3, Key2 = 5, Data = "999" } };

, Π° Ρ‚ΠΈΠΏΡŠΡ‚ Para Π΅ Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½ ΠΊΠ°ΠΊΡ‚ΠΎ слСдва:

ДСфиниция Π½Π° ΠΏΠ°Ρ€Π° Ρ‚ΠΈΠΏ

class Para
{
        public int Key1, Key2;
        public string Data;
}

По Ρ‚ΠΎΠ·ΠΈ Π½Π°Ρ‡ΠΈΠ½ Ρ€Π°Π·Π³Π»Π΅Π΄Π°Ρ…ΠΌΠ΅ някои аспСкти ΠΏΡ€ΠΈ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° LINQ заявки към MS SQL Server.

Π—Π° съТалСниС Π΄ΠΎΡ€ΠΈ ΠΎΠΏΠΈΡ‚Π½ΠΈ ΠΈ Π²ΠΎΠ΄Π΅Ρ‰ΠΈ .NET Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΡ†ΠΈ забравят, Ρ‡Π΅ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° Ρ€Π°Π·Π±Π΅Ρ€Π°Ρ‚ ΠΊΠ°ΠΊΠ²ΠΎ правят инструкциитС, ΠΊΠΎΠΈΡ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Π·Π°Π΄ кулиситС. Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π΅Π½ случай Ρ‚Π΅ стават ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ‚ΠΎΡ€ΠΈ ΠΈ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° поставят Π±ΠΎΠΌΠ±Π° със Π·Π°ΠΊΡŠΡΠ½ΠΈΡ‚Π΅Π» Π² Π±ΡŠΠ΄Π΅Ρ‰Π΅, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΏΡ€ΠΈ ΠΌΠ°Ρ‰Π°Π±ΠΈΡ€Π°Π½Π΅ Π½Π° софтуСрно Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅, Ρ‚Π°ΠΊΠ° ΠΈ ΠΏΡ€ΠΈ Π½Π΅Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»Π½ΠΈ ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ във Π²ΡŠΠ½ΡˆΠ½ΠΈΡ‚Π΅ условия Π½Π° ΠΎΠΊΠΎΠ»Π½Π°Ρ‚Π° срСда.

ИмашС ΠΈ малък ΠΏΡ€Π΅Π³Π»Π΅Π΄ Ρ‚ΡƒΠΊ.

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΡ†ΠΈ Π·Π° тСста - самият ΠΏΡ€ΠΎΠ΅ΠΊΡ‚, ΡΡŠΠ·Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ Π² Π±Π°Π·Π°Ρ‚Π° Π΄Π°Π½Π½ΠΈ TEST, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ ΠΏΠΎΠΏΡŠΠ»Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Ρ‚Π΅Π·ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ с Π΄Π°Π½Π½ΠΈ сС Π½Π°ΠΌΠΈΡ€Π° Ρ‚ΡƒΠΊ.
Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Π² Ρ‚ΠΎΠ²Π° Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ Π² ΠΏΠ°ΠΏΠΊΠ°Ρ‚Π° ПлановС ΠΈΠΌΠ° ΠΏΠ»Π°Π½ΠΎΠ²Π΅ Π·Π° изпълнСниС Π½Π° заявки с Π˜Π›Π˜ условия.

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: www.habr.com

ДобавянС Π½Π° Π½ΠΎΠ² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€