Eminye imiba yokuphucula imibuzo ye-LINQ kwi-C#.NET ye-MS SQL Server

I-LINQ ingene .NET njengolwimi olutsha olunamandla lokukhohlisa. I-LINQ ukuya kwiSQL njengenxalenye yayo ikuvumela ukuba unxibelelane ngokulula neDBMS usebenzisa, umzekelo, Isakhelo seQumrhu. Nangona kunjalo, beyisebenzisa rhoqo, abaphuhlisi bayalibala ukujonga ukuba luhlobo luni lombuzo weSQL umnikezeli obuzwayo, kwimeko yakho iSikhokelo seQumrhu, siyakwenza.

Makhe sijonge iingongoma ezimbini eziphambili sisebenzisa umzekelo.
Ukwenza oku, yenza i-database yoVavanyo kwi-SQL Server, kwaye wenze iitafile ezimbini kuyo usebenzisa lo mbuzo ulandelayo:

Ukudala iitafile

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

Ngoku makhe sigcwalise itheyibhile yeRef ngokuqhuba iskripthi esilandelayo:

Ukuzalisa itheyibhile yeRef

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

Masigcwalise ngokufanayo itheyibhile yoMthengi sisebenzisa esi script silandelayo:

Ukuzalisa itafile yoMthengi

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

Ngaloo ndlela, sifumene iitheyibhile ezimbini, enye enemiqolo yedatha engaphezu kwe-1 yezigidi, kwaye enye inezintlu ezingaphezu kwezigidi ezili-10 zedatha.

Ngoku kwiVisual Studio kufuneka wenze uvavanyo lweVisual C# Console App (.NET Framework) iprojekthi:

Eminye imiba yokuphucula imibuzo ye-LINQ kwi-C#.NET ye-MS SQL Server

Okulandelayo, kufuneka ungeze ithala leencwadi leSikhokelo seQumrhu ukuze linxibelelane nesiseko sedatha.
Ukuyongeza, cofa ekunene kwiprojekthi kwaye ukhethe Lawula iiPakethi zeNuGet kwimenyu yomxholo:

Eminye imiba yokuphucula imibuzo ye-LINQ kwi-C#.NET ye-MS SQL Server

Emva koko, kwifestile yolawulo lwephakheji ye-NuGet evelayo, faka igama elithi "I-Entity Framework" kwifestile yokukhangela kwaye ukhethe iphakheji ye-Entity Framework kwaye uyifake:

Eminye imiba yokuphucula imibuzo ye-LINQ kwi-C#.NET ye-MS SQL Server

Okulandelayo, kwifayile ye-App.config, emva kokuvala i-configSections element, kufuneka udibanise ibhloko elandelayo:

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

Kwintambo yoqhagamshelwano kufuneka ufake umtya woqhagamshelwano.

Ngoku masenze ujongano olu-3 kwiifayile ezahlukeneyo:

  1. Ukusebenzisa i-interface ye-IBaseEntityID
    namespace TestLINQ
    {
        public interface IBaseEntityID
        {
            int ID { get; set; }
        }
    }
    

  2. Ukuphunyezwa kojongano lwe-IBaseEntityName
    namespace TestLINQ
    {
        public interface IBaseEntityName
        {
            string Name { get; set; }
        }
    }
    

  3. Ukuphunyezwa kojongano lwe-IBaseNameInsertUTCDate
    namespace TestLINQ
    {
        public interface IBaseNameInsertUTCDate
        {
            DateTime InsertUTCDate { get; set; }
        }
    }
    

Kwaye kwifayile eyahlukileyo siya kudala isiseko seBaseEntity kumacandelo ethu amabini, aya kubandakanya amasimi aqhelekileyo:

Ukuphunyezwa kwesiseko seBaseEntity

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

Okulandelayo, siya kudala amaziko ethu amabini kwiifayile ezahlukeneyo:

  1. Ukuphunyezwa kweklasi yeRef
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace TestLINQ
    {
        [Table("Ref")]
        public class Ref : BaseEntity
        {
            public int ID2 { get; set; }
        }
    }
    

  2. Ukuphunyezwa kweklasi yoMthengi
    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; }
        }
    }
    

Ngoku masenze umxholo womSebenzisi kwifayile eyahlukileyo:

Ukuphunyezwa kweklasi ye-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; }
    }
}

Sifumene isisombululo esele silungisiwe sokuqhuba iimvavanyo zokufezekisa nge-LINQ ukuya kwi-SQL nge-EF ye-MS SQL Server:

Eminye imiba yokuphucula imibuzo ye-LINQ kwi-C#.NET ye-MS SQL Server

Ngoku faka ikhowudi elandelayo kwifayile yeProgram.cs:

Inkqubo.cs ifayile

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();
            }
        }
    }
}

Okulandelayo, masiqalise iprojekthi yethu.

Ekupheleni komsebenzi, oku kulandelayo kuya kuboniswa kwi-console:

Yenziwe i-SQL Umbuzo

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])

Oko kukuthi, ngokubanzi, umbuzo weLINQ wenze umbuzo weSQL kwi-MS SQL Server DBMS kakuhle.

Ngoku masitshintshe imeko kunye nemeko OKANYE kumbuzo we-LINQ:

Umbuzo weLINQ

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 };

Kwaye masiqalise usetyenziso lwethu kwakhona.

Ukuphunyezwa kuya kuphazamiseka ngempazamo ngenxa yexesha lokuphumeza umyalelo elidlula imizuzwana engama-30:

Eminye imiba yokuphucula imibuzo ye-LINQ kwi-C#.NET ye-MS SQL Server

Ukuba ujonga umbuzo owenziwe yi-LINQ:

Eminye imiba yokuphucula imibuzo ye-LINQ kwi-C#.NET ye-MS SQL Server
, emva koko unokuqinisekisa ukuba ukhetho lwenzeka ngemveliso yeCartesian yeeseti ezimbini (iitafile):

Yenziwe i-SQL Umbuzo

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]

Masiphinde sibhale umbuzo we-LINQ ngolu hlobo lulandelayo:

Umbuzo olungiselelwe iLINQ

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 });

Emva koko sifumana lo mbuzo ulandelayo weSQL:

Umbuzo weSQL

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]

Yeha, kwimibuzo ye-LINQ kunokubakho imeko enye yokudibanisa, ke apha kuyenzeka ukuba wenze umbuzo olinganayo usebenzisa imibuzo emibini kwimeko nganye kwaye emva koko uzidibanise ngeManyano ukususa impinda phakathi kwemigca.
Ewe, imibuzo iya kuba ingalingani, kuthathelwa ingqalelo ukuba irewu eziphindwe kabini zinokubuyiswa. Nangona kunjalo, kubomi bokwenyani, imigca ephindwe kabini ayidingeki kwaye abantu bazama ukuyisusa.

Ngoku makhe sithelekise izicwangciso zokwenza le mibuzo mibini:

  1. ku-CROSS JOIN umndilili wexesha lophumezo yimizuzwana eyi-195:
    Eminye imiba yokuphucula imibuzo ye-LINQ kwi-C#.NET ye-MS SQL Server
  2. ku-INNER JOIN-UNION umndilili wexesha lokwenziwa lingaphantsi kwemizuzwana engama-24:
    Eminye imiba yokuphucula imibuzo ye-LINQ kwi-C#.NET ye-MS SQL Server

Как Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ², для Π΄Π²ΡƒΡ… Ρ‚Π°Π±Π»ΠΈΡ† с ΠΌΠΈΠ»Π»ΠΈΠΎΠ½Π°ΠΌΠΈ записСй ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ LINQ-запрос Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π² Ρ€Π°Π·Ρ‹ быстрСС, Ρ‡Π΅ΠΌ Π½Π΅ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ.

Для Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π° с И Π² условиях LINQ-запрос Π²ΠΈΠ΄Π°:

Umbuzo weLINQ

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 сСк:

Eminye imiba yokuphucula imibuzo ye-LINQ kwi-C#.NET ye-MS SQL Server
Π’Π°ΠΊΠΆΠ΅ для манипуляций LINQ to Objects вмСсто запроса Π²ΠΈΠ΄Π°:

LINQ-запрос (1-ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚)

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-запрос (2-ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚)

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 };

apho:

ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π΄Π²ΡƒΡ… массивов

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 опрСдСляСтся ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠ° Para

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

Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΌΡ‹ рассмотрСли Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ аспСкты Π² ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ LINQ-запросов ΠΊ MS SQL Server.

К соТалСнию Π΄Π°ΠΆΠ΅ ΠΎΠΏΡ‹Ρ‚Π½Ρ‹Π΅ ΠΈ Π²Π΅Π΄ΡƒΡ‰ΠΈΠ΅ .NET-Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π·Π°Π±Ρ‹Π²Π°ΡŽΡ‚ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠΎΠ½ΠΈΠΌΠ°Ρ‚ΡŒ Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π°ΡŽΡ‚ Π·Π° ΠΊΠ°Π΄Ρ€ΠΎΠΌ Ρ‚Π΅ инструкции, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠ½ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚. Π˜Π½Π°Ρ‡Π΅ ΠΎΠ½ΠΈ становятся ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ‚ΠΎΡ€Π°ΠΌΠΈ ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π·Π°Π»ΠΎΠΆΠΈΡ‚ΡŒ Π±ΠΎΠΌΠ±Ρƒ Π·Π°ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎΠ³ΠΎ дСйствия Π² Π±ΡƒΠ΄ΡƒΡ‰Π΅ΠΌ ΠΊΠ°ΠΊ ΠΏΡ€ΠΈ ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ, Ρ‚Π°ΠΊ ΠΈ ΠΏΡ€ΠΈ Π½Π΅Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… измСнСниях Π²Π½Π΅ΡˆΠ½ΠΈΡ… условий срСды.

Π’Π°ΠΊΠΆΠ΅ нСбольшой ΠΎΠ±Π·ΠΎΡ€ проводился ΠΈ apha.

Π˜ΡΡ…ΠΎΠ΄Π½ΠΈΠΊΠΈ для тСста-сам ΠΏΡ€ΠΎΠ΅ΠΊΡ‚, созданиС Ρ‚Π°Π±Π»ΠΈΡ† Π² Π±Π°Π·Π΅ Π΄Π°Π½Π½Ρ‹Ρ… TEST, Π° Ρ‚Π°ΠΊΠΆΠ΅ Π½Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹ΠΌΠΈ этих Ρ‚Π°Π±Π»ΠΈΡ† находится apha.
Kwakhona kule ndawo yokugcina, kwifolda yeZicwangciso, kukho izicwangciso zokwenza imibuzo OKANYE neemeko.

umthombo: www.habr.com

Yongeza izimvo