LINQ نے .NET کو ایک طاقتور نئی ڈیٹا ہیرا پھیری کی زبان کے طور پر داخل کیا ہے۔ LINQ سے SQL اس کے حصے کے طور پر آپ کو DBMS کے ساتھ کافی آسانی سے بات چیت کرنے کی اجازت دیتا ہے، مثال کے طور پر، Entity Framework۔ تاہم، اسے اکثر استعمال کرتے ہوئے، ڈویلپرز یہ دیکھنا بھول جاتے ہیں کہ آپ کے معاملے میں entity Framework، استفسار کرنے والا فراہم کنندہ کس قسم کی 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
اب آئیے درج ذیل اسکرپٹ کو چلا کر ریف ٹیبل کو آباد کرتے ہیں۔
ریف ٹیبل کو بھرنا
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 ملین سے زیادہ قطاریں ہیں۔
اب بصری اسٹوڈیو میں آپ کو ایک ٹیسٹ ویژول C# کنسول ایپ (.NET فریم ورک) پروجیکٹ بنانے کی ضرورت ہے:
اگلا، آپ کو ڈیٹا بیس کے ساتھ تعامل کرنے کے لیے ہستی کے فریم ورک کے لیے ایک لائبریری شامل کرنے کی ضرورت ہے۔
اسے شامل کرنے کے لیے، پروجیکٹ پر دائیں کلک کریں اور سیاق و سباق کے مینو سے NuGet پیکجز کا نظم کریں کو منتخب کریں:
پھر، ظاہر ہونے والی NuGet پیکیج مینجمنٹ ونڈو میں، سرچ ونڈو میں لفظ "Entity Framework" درج کریں اور Entity 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 بنائیں گے، جس میں مشترکہ فیلڈز شامل ہوں گے:
بیس کلاس 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 سیاق و سباق بنائیں:
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();
}
}
}
}
اگلا، آئیے اپنا پروجیکٹ شروع کرتے ہیں۔
کام کے اختتام پر، مندرجہ ذیل کنسول پر دکھایا جائے گا:
ایس کیو ایل استفسار
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 استفسار نے MS SQL Server DBMS کے لیے ایک SQL استفسار بہت اچھی طرح سے تیار کیا۔
اب LINQ استفسار میں AND کی حالت کو OR میں تبدیل کریں:
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 کے ذریعہ تیار کی گئی تھی:
، پھر آپ اس بات کو یقینی بنا سکتے ہیں کہ انتخاب دو سیٹوں (ٹیبلز) کے کارٹیشین مصنوع کے ذریعے ہوتا ہے:
ایس کیو ایل استفسار
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 استفسار:
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