MS SQL سرور لاءِ C#.NET ۾ LINQ سوالن کي بهتر ڪرڻ جا ڪجھ حصا

LINQ .NET هڪ طاقتور نئين ڊيٽا جي استعمال جي ٻولي طور داخل ٿيو. LINQ کان SQL ان جي حصي جي طور تي توھان کي اجازت ڏئي ٿو ڪافي آساني سان ڳالھ ٻولھ ڪرڻ لاءِ DBMS استعمال ڪندي، مثال طور، Entity Framework. جڏهن ته، ان کي اڪثر استعمال ڪندي، ڊولپرز اهو ڏسڻ وساريندا آهن ته ڪهڙي قسم جو SQL سوال پڇڻ وارو مهيا ڪندڙ، توهان جي صورت ۾ اينٽيٽي فريم ورڪ، پيدا ڪندو.

اچو ته هڪ مثال استعمال ڪندي ٻه مکيه نقطا ڏسو.
ائين ڪرڻ لاءِ، SQL سرور ۾ ٽيسٽ ڊيٽابيس ٺاھيو، ۽ ھيٺ ڏنل سوال استعمال ڪندي ان ۾ ٻه ٽيبل ٺاھيو:

ٽيبل ٺاهڻ

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

اچو ته ساڳئي طرح هيٺ ڏنل اسڪرپٽ استعمال ڪندي ڪسٽمر ٽيبل ڀريون:

ڪسٽمر ٽيبل کي آباد ڪرڻ

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 C# Console App (.NET فريم ورڪ) پروجيڪٽ:

MS SQL سرور لاءِ C#.NET ۾ LINQ سوالن کي بهتر ڪرڻ جا ڪجھ حصا

اڳيون، توهان کي ڊيٽابيس سان رابطو ڪرڻ لاءِ اداري فريم ورڪ لاءِ لائبريري شامل ڪرڻ جي ضرورت آهي.
ان کي شامل ڪرڻ لاءِ، پراجيڪٽ تي ساڄي ڪلڪ ڪريو ۽ چونڊيو NuGet Packages کي منظم ڪريو مينيو مان.

MS SQL سرور لاءِ C#.NET ۾ LINQ سوالن کي بهتر ڪرڻ جا ڪجھ حصا

ان کان پوء، NuGet پيڪيج مينيجمينٽ ونڊو ۾ جيڪو ظاهر ٿئي ٿو، لفظ داخل ڪريو "Enity Framework" سرچ ونڊو ۾ ۽ چونڊيو اينٽيٽي فريم ورڪ پيڪيج ۽ ان کي انسٽال ڪريو:

MS SQL سرور لاءِ C#.NET ۾ LINQ سوالن کي بهتر ڪرڻ جا ڪجھ حصا

اڳيون، App.config فائل ۾، configSection عنصر کي بند ڪرڻ کان پوء، توھان کي ھيٺ ڏنل بلاڪ شامل ڪرڻ جي ضرورت آھي:

<connectionStrings>
    <add name="DBConnection" connectionString="data source=ИМЯ_ЭКЗЕМПЛЯРА_MSSQL;Initial Catalog=TEST;Integrated Security=True;" providerName="System.Data.SqlClient" />
</connectionStrings>

ڪنيڪشن اسٽرنگ ۾ توهان کي ڪنيڪشن اسٽرنگ داخل ڪرڻ جي ضرورت آهي.

ھاڻي اچو ته الڳ فائلن ۾ 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 ٺاهينداسين، جنهن ۾ عام شعبا شامل هوندا:

بيس ڪلاس بيس اينٽيٽي جو نفاذ

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 context ٺاهيو:

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

اسان کي MS SQL سرور لاءِ EF ذريعي LINQ کان SQL سان اصلاح جا تجربا ڪرڻ لاءِ تيار ٿيل حل ملي ٿو:

MS SQL سرور لاءِ C#.NET ۾ LINQ سوالن کي بهتر ڪرڻ جا ڪجھ حصا

ھاڻي ھيٺ ڏنل ڪوڊ داخل ڪريو 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 DBMS لاءِ چڱيءَ طرح.

هاڻي اچو ته AND حالت کي OR ۾ تبديل ڪريون 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 سيڪنڊن کان وڌيڪ ڪمانڊ ايگزيڪيوشن جي وقت جي ڪري عمل هڪ غلطي سان حادثو ٿيندو:

MS SQL سرور لاءِ C#.NET ۾ LINQ سوالن کي بهتر ڪرڻ جا ڪجھ حصا

جيڪڏهن توهان ان سوال تي نظر وجهو ٿا جيڪا LINQ پاران ٺاهي وئي هئي:

MS SQL سرور لاءِ C#.NET ۾ LINQ سوالن کي بهتر ڪرڻ جا ڪجھ حصا
، پوءِ توھان پڪ ڪري سگھوٿا ته چونڊ ٻن سيٽن (ٽيبل) جي ڪارٽيزئن پراڊڪٽ ذريعي ٿئي ٿي:

ٺاهيل 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 سوالن ۾ صرف ھڪڙي شامل ٿيڻ واري شرط ٿي سگھي ٿي، تنھنڪري ھتي اھو ممڪن آھي ھڪڙي برابري واري سوال کي استعمال ڪندي ھر شرط لاءِ ٻن سوالن کي استعمال ڪندي ۽ پوءِ انھن کي يونين ذريعي گڏ ڪري قطارن مان نقلن کي ختم ڪرڻ لاءِ.
ها، سوال عام طور تي غير برابر هوندا، انهي حساب ۾ وٺندي ته مڪمل نقل واريون قطارون واپس ٿي سگهن ٿيون. جڏهن ته، حقيقي زندگي ۾، مڪمل نقل واري لائنن جي ضرورت ناهي ۽ ماڻهو انهن کان نجات حاصل ڪرڻ جي ڪوشش ڪندا آهن.

هاڻي اچو ته انهن ٻن سوالن جي عملدرآمد منصوبن جو مقابلو ڪريون:

  1. CROSS JOIN لاءِ سراسري عمل جو وقت 195 سيڪنڊ آهي:
    MS SQL سرور لاءِ C#.NET ۾ LINQ سوالن کي بهتر ڪرڻ جا ڪجھ حصا
  2. INNER JOIN-UNION لاءِ سراسري عمل جو وقت 24 سيڪنڊن کان گھٽ آھي:
    MS SQL سرور لاءِ C#.NET ۾ LINQ سوالن کي بهتر ڪرڻ جا ڪجھ حصا

جئين توھان نتيجن مان ڏسي سگھو ٿا، لکين رڪارڊن سان گڏ ٻن جدولن لاءِ، اصلاحي ڪيل LINQ سوال غير اصلاحي سوال کان ڪيترائي ڀيرا تيز آھي.

شرطن ۾ AND سان اختيار لاءِ، فارم جو هڪ لنڪ سوال:

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 سيڪنڊن ۾ هلندي:

MS SQL سرور لاءِ C#.NET ۾ LINQ سوالن کي بهتر ڪرڻ جا ڪجھ حصا
پڻ LINQ کان آبجیکٹ جي استعمال لاءِ سوال جي بدران:

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

، ۽ پارا قسم جي وضاحت ڪئي وئي آهي هن ريت:

پارا قسم جي تعريف

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

اهڙيء طرح، اسان MS SQL سرور ڏانهن LINQ سوالن کي بهتر ڪرڻ ۾ ڪجهه پهلوئن جي جانچ ڪئي.

بدقسمتي سان، اڃا تائين تجربا ۽ معروف .NET ڊولپرز وساريندا آهن ته انهن کي اهو سمجهڻ جي ضرورت آهي ته اهي جيڪي هدايتون استعمال ڪندا آهن اهي پردي جي پويان ڪندا آهن. ٻي صورت ۾، اهي ترتيب ڏيندڙ بڻجي ويندا آهن ۽ مستقبل ۾ هڪ ٽائيم بم پوکي سگهن ٿا جڏهن سافٽ ويئر حل کي اسڪيل ڪرڻ ۽ خارجي ماحولياتي حالتن ۾ معمولي تبديلين سان.

هڪ مختصر جائزو پڻ ورتو ويو هتي.

ٽيسٽ جا ذريعا - پروجيڪٽ پاڻ، TEST ڊيٽابيس ۾ جدولن جي پيدائش، گڏو گڏ انهن جدولن کي ڀرڻ سان گڏ ڊيٽا موجود آهن هتي.
پڻ ھن مخزن ۾، منصوبا فولڊر ۾، OR شرطن سان سوالن تي عمل ڪرڻ جا منصوبا آھن.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو