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 فريم ورڪ) پروجيڪٽ:
اڳيون، توهان کي ڊيٽابيس سان رابطو ڪرڻ لاءِ اداري فريم ورڪ لاءِ لائبريري شامل ڪرڻ جي ضرورت آهي.
ان کي شامل ڪرڻ لاءِ، پراجيڪٽ تي ساڄي ڪلڪ ڪريو ۽ چونڊيو NuGet Packages کي منظم ڪريو مينيو مان.
ان کان پوء، NuGet پيڪيج مينيجمينٽ ونڊو ۾ جيڪو ظاهر ٿئي ٿو، لفظ داخل ڪريو "Enity Framework" سرچ ونڊو ۾ ۽ چونڊيو اينٽيٽي فريم ورڪ پيڪيج ۽ ان کي انسٽال ڪريو:
اڳيون، App.config فائل ۾، configSection عنصر کي بند ڪرڻ کان پوء، توھان کي ھيٺ ڏنل بلاڪ شامل ڪرڻ جي ضرورت آھي:
<connectionStrings>
<add name="DBConnection" connectionString="data source=ИМЯ_ЭКЗЕМПЛЯРА_MSSQL;Initial Catalog=TEST;Integrated Security=True;" providerName="System.Data.SqlClient" />
</connectionStrings>
ڪنيڪشن اسٽرنگ ۾ توهان کي ڪنيڪشن اسٽرنگ داخل ڪرڻ جي ضرورت آهي.
ھاڻي اچو ته الڳ فائلن ۾ 3 انٽرفيس ٺاھيون:
- IBaseEntityID انٽرفيس کي لاڳو ڪرڻ
namespace TestLINQ { public interface IBaseEntityID { int ID { get; set; } } }
- IBaseEntityName انٽرفيس جو نفاذ
namespace TestLINQ { public interface IBaseEntityName { string Name { get; set; } } }
- 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; }
}
}
اڳيون، اسان الڳ الڳ فائلن ۾ اسان جا ٻه ادارا ٺاهينداسين:
- ريف ڪلاس جو نفاذ
using System.ComponentModel.DataAnnotations.Schema; namespace TestLINQ { [Table("Ref")] public class Ref : BaseEntity { public int ID2 { get; set; } } }
- ڪسٽمر ڪلاس جو نفاذ
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 سان اصلاح جا تجربا ڪرڻ لاءِ تيار ٿيل حل ملي ٿو:
ھاڻي ھيٺ ڏنل ڪوڊ داخل ڪريو 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 سيڪنڊن کان وڌيڪ ڪمانڊ ايگزيڪيوشن جي وقت جي ڪري عمل هڪ غلطي سان حادثو ٿيندو:
جيڪڏهن توهان ان سوال تي نظر وجهو ٿا جيڪا 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 سوالن ۾ صرف ھڪڙي شامل ٿيڻ واري شرط ٿي سگھي ٿي، تنھنڪري ھتي اھو ممڪن آھي ھڪڙي برابري واري سوال کي استعمال ڪندي ھر شرط لاءِ ٻن سوالن کي استعمال ڪندي ۽ پوءِ انھن کي يونين ذريعي گڏ ڪري قطارن مان نقلن کي ختم ڪرڻ لاءِ.
ها، سوال عام طور تي غير برابر هوندا، انهي حساب ۾ وٺندي ته مڪمل نقل واريون قطارون واپس ٿي سگهن ٿيون. جڏهن ته، حقيقي زندگي ۾، مڪمل نقل واري لائنن جي ضرورت ناهي ۽ ماڻهو انهن کان نجات حاصل ڪرڻ جي ڪوشش ڪندا آهن.
هاڻي اچو ته انهن ٻن سوالن جي عملدرآمد منصوبن جو مقابلو ڪريون:
- CROSS JOIN لاءِ سراسري عمل جو وقت 195 سيڪنڊ آهي:
- INNER JOIN-UNION لاءِ سراسري عمل جو وقت 24 سيڪنڊن کان گھٽ آھي:
جئين توھان نتيجن مان ڏسي سگھو ٿا، لکين رڪارڊن سان گڏ ٻن جدولن لاءِ، اصلاحي ڪيل 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 سيڪنڊن ۾ هلندي:
پڻ 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