Ezinye izici zokuthuthukisa imibuzo ye-LINQ ku-C#.NET ye-MS SQL Server

I-LINQ ifake i-.NET njengolimi olusha olunamandla lokukhohlisa idatha. I-LINQ kuya ku-SQL njengengxenye yayo ikuvumela ukuthi uxhumane kalula ne-DBMS usebenzisa, isibonelo, i-Entity Framework. Kodwa-ke, uma beyisebenzisa kaningi, abathuthukisi bayakhohlwa ukubheka ukuthi hlobo luni lombuzo we-SQL umhlinzeki ongabuzwa, esimweni sakho I-Entity Framework, azoyenza.

Ake sibheke amaphuzu amabili abalulekile sisebenzisa isibonelo.
Ukuze wenze lokhu, dala isizindalwazi sokuhlola ku-SQL Server, bese udala amatafula amabili kuyo usebenzisa lo mbuzo olandelayo:

Ukudala amatafula

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

Manje ake sigcwalise ithebula le-Ref ngokusebenzisa umbhalo olandelayo:

Ukugcwalisa ithebula leRef

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 ithebula Lekhasimende sisebenzisa umbhalo olandelayo:

Ukugcwalisa ithebula Lekhasimende

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

Ngakho, sithole amathebula amabili, elilodwa linemigqa yedatha engaphezu kwesigidi, kanti elinye linemigqa yedatha engaphezu kwezigidi ezingu-1.

Manje ku-Visual Studio udinga ukudala iphrojekthi yokuhlola ye-Visual C# Console App (.NET Framework):

Ezinye izici zokuthuthukisa imibuzo ye-LINQ ku-C#.NET ye-MS SQL Server

Okulandelayo, udinga ukwengeza umtapo wolwazi ukuze Uhlaka Lwebhizinisi luhlanganyele nesizindalwazi.
Ukuze uyengeze, chofoza kwesokudla kuphrojekthi bese ukhetha Phatha amaphakheji we-NuGet kumenyu yokuqukethwe:

Ezinye izici zokuthuthukisa imibuzo ye-LINQ ku-C#.NET ye-MS SQL Server

Bese, efasiteleni lokuphatha iphakheji le-NuGet elivelayo, faka igama elithi β€œEntity Framework” efasiteleni lokusesha bese ukhetha iphakethe le-Entity Framework bese ulifaka:

Ezinye izici zokuthuthukisa imibuzo ye-LINQ ku-C#.NET ye-MS SQL Server

Okulandelayo, kufayela le-App.config, ngemva kokuvala isici se-configSections, udinga ukwengeza ibhulokhi elandelayo:

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

Ku-ConnectionString udinga ukufaka intambo yokuxhuma.

Manje ake sakhe izixhumanisi ezi-3 kumafayela ahlukene:

  1. Ukusebenzisa isixhumi esibonakalayo se-IBaseEntityID
    namespace TestLINQ
    {
        public interface IBaseEntityID
        {
            int ID { get; set; }
        }
    }
    

  2. Ukuqaliswa kokusetshenziswa kubonwa kwe-IBaseEntityName
    namespace TestLINQ
    {
        public interface IBaseEntityName
        {
            string Name { get; set; }
        }
    }
    

  3. Ukuqaliswa kokusetshenziswa kubonwa kwe-IBaseNameInsertUTCDate
    namespace TestLINQ
    {
        public interface IBaseNameInsertUTCDate
        {
            DateTime InsertUTCDate { get; set; }
        }
    }
    

Futhi efayeleni elihlukile sizodala i-BaseEntity yesigaba sesisekelo sezinhlangano zethu ezimbili, ezizofaka izinkambu ezivamile:

Ukuqaliswa kwe-base class BaseEntity

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

Okulandelayo, sizodala izinhlangano zethu ezimbili ngamafayela ahlukene:

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

  2. Ukuqaliswa kwekilasi leKhasimende
    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; }
        }
    }
    

Manje ake sakhe umongo we-UserContext efayeleni elihlukile:

Ukuqaliswa kwekilasi le-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; }
    }
}

Sithole isixazululo esenziwe ngomumo sokwenza izivivinyo zokuthuthukisa nge-LINQ kuya ku-SQL nge-EF ye-MS SQL Server:

Ezinye izici zokuthuthukisa imibuzo ye-LINQ ku-C#.NET ye-MS SQL Server

Manje faka ikhodi elandelayo efayeleni le-Program.cs:

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

Okulandelayo, ake sethule iphrojekthi yethu.

Ekupheleni komsebenzi, okulandelayo kuzovezwa kukhonsoli:

Kwenziwe Umbuzo we-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])

Okusho ukuthi, ngokujwayelekile, umbuzo we-LINQ ukhiqize umbuzo we-SQL ku-MS SQL Server DBMS kahle kakhulu.

Manje ake siguqule isimo KANYE sibe NOMA embuzweni we-LINQ:

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

Futhi masiqalise uhlelo lwethu lokusebenza futhi.

Ukwenza kuzophahlazeka ngephutha ngenxa yesikhathi sokwenza umyalo esidlula imizuzwana engama-30:

Ezinye izici zokuthuthukisa imibuzo ye-LINQ ku-C#.NET ye-MS SQL Server

Uma ubheka umbuzo owenziwe yi-LINQ:

Ezinye izici zokuthuthukisa imibuzo ye-LINQ ku-C#.NET ye-MS SQL Server
, khona-ke ungaqiniseka ukuthi ukukhetha kwenzeka ngomkhiqizo weCartesian wamasethi amabili (amatafula):

Kwenziwe Umbuzo we-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]

Masibhale kabusha umbuzo we-LINQ kanje:

Kulungiselelwe umbuzo we-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 });

Bese sithola umbuzo olandelayo we-SQL:

Umbuzo we-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]

Maye, emibuzweni ye-LINQ kungaba nesimo sokujoyina esisodwa kuphela, ngakho-ke lapha kungenzeka ukwenza umbuzo olinganayo usebenzisa imibuzo emibili kusimo ngasinye bese uyihlanganisa nge-Union ukuze ukhiphe izimpinda phakathi kwemigqa.
Yebo, imibuzo ngokuvamile ngeke ilingane, kucatshangelwa ukuthi imigqa eyimpinda ephelele ingase ibuyiswe. Kodwa-ke, empilweni yangempela, imigqa eyimpinda ephelele ayidingeki futhi abantu bazama ukuyisusa.

Manje ake siqhathanise izinhlelo zokusebenza zale mibuzo emibili:

  1. kokuthi CROSS JOIN isikhathi sokwenza esimaphakathi amasekhondi angu-195:
    Ezinye izici zokuthuthukisa imibuzo ye-LINQ ku-C#.NET ye-MS SQL Server
  2. ku-INNER JOIN-UNION isikhathi sokwenza esimaphakathi singaphansi kwamasekhondi angu-24:
    Ezinye izici zokuthuthukisa imibuzo ye-LINQ ku-C#.NET ye-MS SQL Server

Njengoba ubona emiphumeleni, kumathebula amabili anezigidi zamarekhodi, umbuzo we-LINQ olungiselelwe ushesha izikhathi eziningi kunalowo ongalungiselelwe.

Ngenketho ethi KANYE ngaphansi kwezimo, umbuzo we-LINQ wefomu:

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

Umbuzo olungile we-SQL uzohlale ukhiqizwa, okuzosebenza ngokwesilinganiso cishe kusekhondi elingu-1:

Ezinye izici zokuthuthukisa imibuzo ye-LINQ ku-C#.NET ye-MS SQL Server
Futhi nge-LINQ kuya ku-Objects manipulations esikhundleni sombuzo ofana:

Umbuzo we-LINQ (inketho yokuqala)

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

ungasebenzisa umbuzo onjengokuthi:

Umbuzo we-LINQ (inketho yokuqala)

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

lapho:

Ichaza amaqembu afanayo amabili

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

, futhi uhlobo lwe-Para luchazwa kanje:

Para Type Definition

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

Ngakho-ke, sihlole izici ezithile ekulungiseleleni imibuzo ye-LINQ ku-MS SQL Server.

Ngeshwa, ngisho nabathuthukisi be-.NET abanolwazi nabaholayo bayakhohlwa ukuthi badinga ukuqonda ukuthi imiyalelo abayisebenzisayo yenzani ngemuva kwezigcawu. Uma kungenjalo, baba abahleli futhi bangatshala ibhomu lesikhathi esikhathini esizayo kokubili lapho bekala isisombululo sesofthiwe kanye nezinguquko ezincane ezimweni zemvelo zangaphandle.

Ukubuyekezwa okufushane nakho kwenziwa lapha.

Imithombo yokuhlolwa - iphrojekthi ngokwayo, ukwakhiwa kwamatafula kusizindalwazi se-TEST, kanye nokugcwalisa lawa mathebula ngedatha atholakala. lapha.
Futhi kule nqolobane, kufolda Yezinhlelo, kunezinhlelo zokwenza imibuzo ngemibandela NOMA.

Source: www.habr.com

Engeza amazwana