লিনকের সাথে আইকিউয়েরেবল ব্যবহার করা


256

IQueryableলিনকিউ এর প্রসঙ্গে কী ব্যবহার ?

এটি সম্প্রসারণ পদ্ধতি বা অন্য কোনও উদ্দেশ্যে বিকাশের জন্য ব্যবহৃত হয়?

উত্তর:


507

মার্ক গ্র্যাভেলের উত্তরটি সম্পূর্ণ সম্পূর্ণ, তবে আমি ভেবেছিলাম ব্যবহারকারীর দৃষ্টিকোণ থেকে আমি এ সম্পর্কে কিছু যুক্ত করব, ...


ব্যবহারকারীর দৃষ্টিকোণ থেকে মূল পার্থক্য হ'ল আপনি যখন ব্যবহার করবেন use IQueryable<T> (এমন কোনও সরবরাহকারীর সাথে যা জিনিসকে সঠিকভাবে সমর্থন করে) আপনি প্রচুর সংস্থান সংরক্ষণ করতে পারেন।

উদাহরণস্বরূপ, আপনি যদি অনেকগুলি ওআরএম সিস্টেমের সাথে কোনও দূরবর্তী ডাটাবেসের বিরুদ্ধে কাজ করছেন তবে আপনার কাছে দুটি উপায়ে একটি টেবিল থেকে ডেটা আনার বিকল্প রয়েছে, একটি যা প্রত্যাবর্তন করে IEnumerable<T>এবং একটি যা প্রত্যাবর্তন করে IQueryable<T>। বলুন, উদাহরণস্বরূপ, আপনার কাছে একটি পণ্য সারণী রয়েছে এবং আপনি যে সমস্ত পণ্যগুলির দাম> $ 25 হয় তার সমস্ত পেতে চান।

যদি তুমি করো:

 IEnumerable<Product> products = myORM.GetProducts();
 var productsOver25 = products.Where(p => p.Cost >= 25.00);

এখানে কী ঘটে, ডাটাবেস হ'ল সমস্ত পণ্য লোড হয় এবং সেগুলি আপনার কম্পিউটারে সরবরাহ করে। আপনার প্রোগ্রামটি তখন ডেটা ফিল্টার করে। সংক্ষেপে, ডাটাবেসটি একটি করে SELECT * FROM Products, এবং আপনাকে প্রতিটি পণ্য প্রদান করে।

অন্যদিকে সঠিক IQueryable<T>সরবরাহকারীর সাহায্যে আপনি এটি করতে পারেন:

 IQueryable<Product> products = myORM.GetQueryableProducts();
 var productsOver25 = products.Where(p => p.Cost >= 25.00);

কোডটি দেখতে একই রকম, তবে এখানে পার্থক্য হ'ল কার্যকর করা এসকিউএল হবে SELECT * FROM Products WHERE Cost >= 25

বিকাশকারী হিসাবে আপনার পিওভি থেকে, এটি দেখতে একই রকম। তবে, পারফরম্যান্সের দিক থেকে আপনি কেবলমাত্র 20,000 এর পরিবর্তে নেটওয়ার্ক জুড়ে 2 টি রেকর্ড ফিরিয়ে দিতে পারেন ....


9
"গেটিক্যুয়েরিপ্রোডাক্টস ();" এর সংজ্ঞা কোথায়?
পঙ্কজ

12
@ স্ট্যাকওভারফ্লোউজার এটি এমন কোনও পদ্ধতি হিসাবে প্রত্যাবর্তন IQueryable<Product>করবে যা কোনও ফেরত দেয় - এটি আপনার ওআরএম বা সংগ্রহশালা ইত্যাদির জন্য নির্দিষ্ট হবে
রিড কোপসি

ঠিক আছে। তবে আপনি উল্লেখ করেছেন কোথায় এই ফাংশন কল করার পরে ধারা। সুতরাং সিস্টেম এখনও ফিল্টার সম্পর্কে অজানা। আমার অর্থ এটি এখনও পণ্যগুলির সমস্ত রেকর্ড আনে। ঠিক আছে?
পঙ্কজ

@ স্ট্যাকওভারফ্লোউজার নং - এটি আইকিউয়ারেবল <T> এর সৌন্দর্য - আপনি ফলাফল পেলে মূল্যায়ন করার জন্য এটি সেটআপ করা যেতে পারে - যার অর্থ হ'ল ধারাটি সত্যতার পরে ব্যবহৃত সার্ভারে চালিত এসকিউএল বিবৃতিতে অনুবাদ করা হবে এবং কেবল তারের জুড়ে প্রয়োজনীয় উপাদানগুলি টানুন ...
রিড কোপসি

40
@ টেস্টিং আপনি আসলে এখনও ডিবিতে যাচ্ছেন না। যতক্ষণ না আপনি আসলে ফলাফলগুলি গণনা করেন (যেমন: একটি ব্যবহার করুন foreach, বা কল করুন ToList()), আপনি আসলে ডিবিতে আঘাত করবেন না।
রিড কোপসি

188

সংক্ষেপে এটির কাজটি একটি অনুরূপ IEnumerable<T>ডেটা উত্সকে উপস্থাপন করতে - বিভিন্ন লিংক পদ্ধতি (অন Queryable) Expressionপ্রতিনিধিদের চেয়ে গাছ ব্যবহার করে কোয়েরিটি তৈরি করা আরও নির্দিষ্ট হতে পারে (এটি কীEnumerable

আপনার পছন্দসই লিনকিউ সরবরাহকারী দ্বারা অভিব্যক্তি গাছগুলি পরিদর্শন করা যেতে পারে এবং একটি আসল জিজ্ঞাসায় পরিণত হতে পারে - যদিও এটি নিজের মধ্যে একটি কালো শিল্প।

এটি সত্যিই নীচে নেমে এসেছে ElementType, Expressionএবং Provider- তবে বাস্তবে আপনাকে ব্যবহারকারী হিসাবে খুব কমই এ সম্পর্কে যত্ন নেওয়া প্রয়োজন । কেবলমাত্র একটি লিনকিউ প্রয়োগকারীকে বিশ্রী বিবরণগুলি জানতে হবে।


মন্তব্যসমূহ; উদাহরণস্বরূপ আপনি কী চান তা আমি নিশ্চিত নই, তবে লিনকুই-টু এসকিউএল বিবেচনা করুন; এখানে কেন্দ্রীয় অবজেক্টটি একটি DataContext, যা আমাদের ডাটাবেস-মোড়কে উপস্থাপন করে। এটিতে সাধারণত প্রতি টেবিলের সম্পত্তি থাকে (উদাহরণস্বরূপ Customers), এবং একটি টেবিল সরঞ্জাম রয়েছে IQueryable<Customer>। তবে আমরা এগুলি সরাসরি ব্যবহার করি না; বিবেচনা:

using(var ctx = new MyDataContext()) {
    var qry = from cust in ctx.Customers
              where cust.Region == "North"
              select new { cust.Id, cust.Name };
    foreach(var row in qry) {
        Console.WriteLine("{0}: {1}", row.Id, row.Name);
    }
}

এটি হয়ে যায় (সি # সংকলক দ্বারা):

var qry = ctx.Customers.Where(cust => cust.Region == "North")
                .Select(cust => new { cust.Id, cust.Name });

যা আবার ব্যাখ্যা করা হয়েছে (সি # সংকলক দ্বারা) হিসাবে:

var qry = Queryable.Select(
              Queryable.Where(
                  ctx.Customers,
                  cust => cust.Region == "North"),
              cust => new { cust.Id, cust.Name });

গুরুত্বপূর্ণভাবে, Queryableটেক অফ এক্সপ্রেশন ট্রিগুলিতে স্থিতিশীল পদ্ধতিগুলি , যা নিয়মিত আইএল না করে কোনও বস্তুর মডেলটিতে সংকলিত হয়। উদাহরণস্বরূপ - কেবল "কোথায়" তাকান, এটি আমাদের সাথে তুলনা করার মতো কিছু দেয়:

var cust = Expression.Parameter(typeof(Customer), "cust");
var lambda = Expression.Lambda<Func<Customer,bool>>(
                  Expression.Equal(
                      Expression.Property(cust, "Region"),
                      Expression.Constant("North")
                  ), cust);

... Queryable.Where(ctx.Customers, lambda) ...

সংকলকটি আমাদের জন্য অনেক কিছু করেনি? এই অবজেক্টের মডেলটি ছিন্ন-বিচ্ছিন্ন হতে পারে, এর অর্থ কী তা পরীক্ষা করাতে পারে এবং টিএসকিউএল জেনারেটর দ্বারা আবার একসাথে রাখা যেতে পারে - এরকম কিছু দেওয়া:

 SELECT c.Id, c.Name
 FROM [dbo].[Customer] c
 WHERE c.Region = 'North'

(স্ট্রিংটি প্যারামিটার হিসাবে শেষ হতে পারে; আমি মনে করতে পারি না)

যদি আমরা কেবল একটি প্রতিনিধি ব্যবহার করে থাকি তবে এর কিছুই সম্ভব হবে না। আর এই বিন্দু Queryable/ IQueryable<T>: এটা মত প্রকাশের গাছ ব্যবহার করার জন্য এন্ট্রি দফা প্রদান করে।

এগুলি সবই জটিল, সুতরাং এটি খুব ভাল কাজ যে সংকলকটি এটি আমাদের জন্য সুন্দর এবং সহজ করে তুলেছে।

আরও তথ্যের জন্য, " ডিপথ ইন সি # " বা " লিনকিউ ইন অ্যাকশন " দেখুন, উভয়ই এই বিষয়গুলির কভারেজ সরবরাহ করে।


2
আপনি যদি আপত্তি না করেন আপনি কি আমাকে সহজ বোধগম্য উদাহরণ দিয়ে আপডেট করতে পারেন (যদি আপনার সময় থাকে)।
ব্যবহারকারী190560

আপনি কী "গেটিক্যুয়েরেবল প্রোডাক্টস () এর সংজ্ঞাটি কোথায় তা ব্যাখ্যা করতে পারেন; "?" মিঃ রেড কোপসে জবাব
পঙ্কজ

কোনও প্রশ্নের সাথে
বাক্যগুলির

আপনি যদি কোনও প্রতিনিধি ব্যবহার করে থাকেন তবে কেন এটির কোনওটিই সম্ভব হবে না?
ডেভিড ক্লেম্পফনার

1
@ ব্যাকওয়ার্ডস_ ডেভ কারণ একটি প্রতিনিধি আইএলকে নির্দেশ করে (মূলত), এবং আইএল এসকিউএল তৈরির উদ্দেশ্যে অভিপ্রায়টি ডিকনস্ট্রাক্ট করার চেষ্টা করার পক্ষে যুক্তিসঙ্গতভাবে যথেষ্ট ব্যাখ্যা করে না। আইএল অনেকগুলি জিনিসও মঞ্জুরি দেয় - যেমন বেশিরভাগ বিষয় যা আইএল-তে প্রকাশ করা যায় সীমাবদ্ধ বাক্যবিন্যাসে প্রকাশ করা যায়নি যে এসকিউএল
মার্ক গ্র্যাভেল

17

যদিও রিড Copsey এবং মার্ক Gravell ইতিমধ্যে সম্পর্কে বর্ণনা IQueryable(এবং IEnumerable) যথেষ্ট, MI উপর একটি ছোট উদাহরণ প্রদানের মাধ্যমে একটু বেশি এখানে যোগ করতে চান IQueryableএবংIEnumerable অনেক ব্যবহারকারী এটি চেয়েছিলেন বলে

উদাহরণ : আমি ডাটাবেসে দুটি টেবিল তৈরি করেছি

   CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Gender] [nchar](1) NOT NULL)
   CREATE TABLE [dbo].[Person]([PersonId] [int] NOT NULL PRIMARY KEY,[FirstName] [nvarchar](50) NOT NULL,[LastName] [nvarchar](50) NOT NULL)

PersonIdসারণীর প্রাথমিক কী ( ) Employeeহ'ল ফোরজিন কী (personid )Person

এরপরে আমি আমার অ্যাপ্লিকেশনটিতে অ্যাডো নেট নেট সত্তা মডেল যুক্ত করেছি এবং সেবার নীচে পরিষেবা শ্রেণি তৈরি করব

public class SomeServiceClass
{   
    public IQueryable<Employee> GetEmployeeAndPersonDetailIQueryable(IEnumerable<int> employeesToCollect)
    {
        DemoIQueryableEntities db = new DemoIQueryableEntities();
        var allDetails = from Employee e in db.Employees
                         join Person p in db.People on e.PersonId equals p.PersonId
                         where employeesToCollect.Contains(e.PersonId)
                         select e;
        return allDetails;
    }

    public IEnumerable<Employee> GetEmployeeAndPersonDetailIEnumerable(IEnumerable<int> employeesToCollect)
    {
        DemoIQueryableEntities db = new DemoIQueryableEntities();
        var allDetails = from Employee e in db.Employees
                         join Person p in db.People on e.PersonId equals p.PersonId
                         where employeesToCollect.Contains(e.PersonId)
                         select e;
        return allDetails;
    }
}

তাদের একই লিঙ্ক রয়েছে। এটি program.csনীচে সংজ্ঞায়িত হিসাবে বলা হয়

class Program
{
    static void Main(string[] args)
    {
        SomeServiceClass s= new SomeServiceClass(); 

        var employeesToCollect= new []{0,1,2,3};

        //IQueryable execution part
        var IQueryableList = s.GetEmployeeAndPersonDetailIQueryable(employeesToCollect).Where(i => i.Gender=="M");            
        foreach (var emp in IQueryableList)
        {
            System.Console.WriteLine("ID:{0}, EName:{1},Gender:{2}", emp.PersonId, emp.Person.FirstName, emp.Gender);
        }
        System.Console.WriteLine("IQueryable contain {0} row in result set", IQueryableList.Count());

        //IEnumerable execution part
        var IEnumerableList = s.GetEmployeeAndPersonDetailIEnumerable(employeesToCollect).Where(i => i.Gender == "M");
        foreach (var emp in IEnumerableList)
        {
           System.Console.WriteLine("ID:{0}, EName:{1},Gender:{2}", emp.PersonId, emp.Person.FirstName, emp.Gender);
        }
        System.Console.WriteLine("IEnumerable contain {0} row in result set", IEnumerableList.Count());

        Console.ReadKey();
    }
}

স্পষ্টত উভয় জন্য আউটপুট একই

ID:1, EName:Ken,Gender:M  
ID:3, EName:Roberto,Gender:M  
IQueryable contain 2 row in result set  
ID:1, EName:Ken,Gender:M  
ID:3, EName:Roberto,Gender:M  
IEnumerable contain 2 row in result set

সুতরাং প্রশ্নটি কি / কোথায় পার্থক্য আছে? মনে হচ্ছে না কোন পার্থক্য আছে ঠিক? সত্যিই !!

আসুন এই সময়কালে সত্তা ফ্রেমওয়ার্ক 5 দ্বারা উত্পাদিত এবং সম্পাদিত এসকিএল ক্যোয়ারীগুলি একবার দেখে নেওয়া যাক

আইকিউয়েরেবল এক্সিকিউশন অংশ

--IQueryableQuery1 
SELECT 
[Extent1].[PersonId] AS [PersonId], 
[Extent1].[Gender] AS [Gender]
FROM [dbo].[Employee] AS [Extent1]
WHERE ([Extent1].[PersonId] IN (0,1,2,3)) AND (N'M' = [Extent1].[Gender])

--IQueryableQuery2
SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    COUNT(1) AS [A1]
    FROM [dbo].[Employee] AS [Extent1]
    WHERE ([Extent1].[PersonId] IN (0,1,2,3)) AND (N'M' = [Extent1].[Gender])
)  AS [GroupBy1]

আইকনামেবল এক্সিকিউশন অংশ

--IEnumerableQuery1
SELECT 
[Extent1].[PersonId] AS [PersonId], 
[Extent1].[Gender] AS [Gender]
FROM [dbo].[Employee] AS [Extent1]
WHERE [Extent1].[PersonId] IN (0,1,2,3)

--IEnumerableQuery2
SELECT 
[Extent1].[PersonId] AS [PersonId], 
[Extent1].[Gender] AS [Gender]
FROM [dbo].[Employee] AS [Extent1]
WHERE [Extent1].[PersonId] IN (0,1,2,3)

উভয় নির্বাহ অংশের জন্য সাধারণ স্ক্রিপ্ট

/* these two query will execute for both IQueryable or IEnumerable to get details from Person table
   Ignore these two queries here because it has nothing to do with IQueryable vs IEnumerable
--ICommonQuery1 
exec sp_executesql N'SELECT 
[Extent1].[PersonId] AS [PersonId], 
[Extent1].[FirstName] AS [FirstName], 
[Extent1].[LastName] AS [LastName]
FROM [dbo].[Person] AS [Extent1]
WHERE [Extent1].[PersonId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1

--ICommonQuery2
exec sp_executesql N'SELECT 
[Extent1].[PersonId] AS [PersonId], 
[Extent1].[FirstName] AS [FirstName], 
[Extent1].[LastName] AS [LastName]
FROM [dbo].[Person] AS [Extent1]
WHERE [Extent1].[PersonId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=3
*/

সুতরাং আপনার এখন কয়েকটি প্রশ্ন রয়েছে, আমাকে সেগুলি অনুমান করতে দিন এবং তাদের উত্তর দেওয়ার চেষ্টা করুন

একই ফলাফলের জন্য কেন বিভিন্ন স্ক্রিপ্ট তৈরি করা হয়?

এখানে কিছু পয়েন্ট খুঁজে পেতে দিন,

সমস্ত প্রশ্নের একটি সাধারণ অংশ রয়েছে

WHERE [Extent1].[PersonId] IN (0,1,2,3)

কেন? কারণ উভয় ফাংশন IQueryable<Employee> GetEmployeeAndPersonDetailIQueryableএবং IEnumerable<Employee> GetEmployeeAndPersonDetailIEnumerableএর SomeServiceClassলিনক ক্যোয়ারিতে একটি সাধারণ লাইন থাকে

where employeesToCollect.Contains(e.PersonId)

AND (N'M' = [Extent1].[Gender])পার্টটি IEnumerableএক্সিকিউশন অংশে অনুপস্থিত কেন , উভয় ফাংশন কলিংয়ে আমরা Where(i => i.Gender == "M") inপ্রোগ্রামের সিএস ব্যবহার করেছি Than

এখন আমরা সেই বিন্দুতে এসেছি যেখানে পার্থক্য এসেছিল IQueryableএবং এর মধ্যেIEnumerable

সত্তা ফ্রেমওয়ার্ক যখন একটি করে IQueryable পদ্ধতিটি , এটি পদ্ধতির অভ্যন্তরে লিঙ্কযুক্ত বিবৃতিটি চেয়েছিল এবং ফলাফলের উপর আরও লিনাকের অভিব্যক্তি সংজ্ঞায়িত করা হয়েছে কিনা তা অনুসন্ধান করার চেষ্টা করে, ফলস্বরূপ ফলাফল আনার প্রয়োজন না হওয়া পর্যন্ত এটি নির্ধারিত সমস্ত লিনক কোয়েরি সংগ্রহ করে এবং আরও যথাযথ স্কয়ার তৈরি করে কার্যকর করতে জিজ্ঞাসা।

এটি প্রচুর উপকার সরবরাহ করে যেমন,

  • কেবলমাত্র এসকিএল সার্ভার দ্বারা জনবহুল সারিগুলি যা পুরো লিনক ক্যোয়ারী এক্সিকিউশন দ্বারা বৈধ হতে পারে
  • অপ্রয়োজনীয় সারিগুলি না নির্বাচন করে স্কয়ার সার্ভারের কার্য সম্পাদনে সহায়তা করে
  • নেটওয়ার্ক ব্যয় হ্রাস পেতে

এখানে যেমন উদাহরণস্বরূপ, এসকিউএল সার্ভার আইকুয়েরেবল এক্সিকিউটিশনের পরে মাত্র দুটি সারি প্রয়োগ করে ফিরে এসেছিল - তবে তিনটি সারি ফিরিয়েছে কেন আইক্যুয়্যারি ক্যোয়ারির জন্য?

IEnumerableপদ্ধতির ক্ষেত্রে , সত্তা কাঠামোটি পদ্ধতির অভ্যন্তরে লিঙ্কযুক্ত বিবৃতি গ্রহণ করে এবং যখন ফলাফল আনার দরকার হয় তখন স্কিল কোয়েরি তৈরি করে। এটিতে স্কিল কোয়েরি তৈরির জন্য বিশ্রামের লিঙ্ক অংশ অন্তর্ভুক্ত নয়। এখানে যেমন কলামে স্কেল সার্ভারে কোনও ফিল্টারিং করা হয় না gender

কিন্তু ফলাফল কি একই? কারণ 'এসকিউএল সার্ভার থেকে ফলাফল পুনরুদ্ধার করার পরে আইনুনামেবল ফল প্রয়োগের পর্যায়ে আরও ফিল্টার করে

সুতরাং, কেউ কি চয়ন করা উচিত? আমি ব্যক্তিগতভাবে ফাংশন ফলাফল সংজ্ঞায়িত করতে পছন্দ করি IQueryable<T>কারণ এতে প্রচুর সুবিধা রয়েছেIEnumerable , আপনি দু'একটি বেশি আইকিউয়েরেবল ফাংশনগুলিতে যোগ দিতে পারেন, যা এসকিউএল সার্ভারে আরও নির্দিষ্ট স্ক্রিপ্ট তৈরি করে।

এখানে উদাহরণস্বরূপ আপনি দেখতে পাচ্ছেন IQueryable Query(IQueryableQuery2)যে একটি আরও নির্দিষ্ট স্ক্রিপ্ট তৈরি করা হয়েছে IEnumerable query(IEnumerableQuery2)যা আমার দৃষ্টিতে অনেক বেশি গ্রহণযোগ্য।


2

এটি আরও লাইনটি আরও জিজ্ঞাসা করার অনুমতি দেয়। যদি এটি কোনও পরিষেবার সীমানার বাইরে ছিল, তবে এই আইকিউয়েরেবল অবজেক্টটির ব্যবহারকারীকে এর সাথে আরও কিছু করার অনুমতি দেওয়া হবে।

উদাহরণস্বরূপ আপনি যদি নিবারনেটের সাথে অলস লোডিং ব্যবহার করে থাকেন তবে প্রয়োজনে / যখন প্রয়োজন হয় গ্রাফটি লোড হতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.