লিনক সহ আইডির তালিকার উপর ভিত্তি করে একাধিক রেকর্ড নির্বাচন করুন


122

আমার UserProfileটেবিলে আইডিসহ একটি তালিকা রয়েছে। আমি UserProfilesযে আইডির varব্যবহার পেয়েছি তার তালিকার উপর ভিত্তি করে কীভাবে সমস্ত নির্বাচন করতে পারি LINQ?

var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(......);

আমি এখনই আটকে গেলাম। আমি লুপ ইত্যাদির সাহায্যে এটি করতে পারি তবে আমি এটির পরিবর্তে এটি করব LINQ


4
অনুসন্ধান এবং সন্ধান 2 ভিন্ন জিনিস। আপনি যেহেতু আমার কাঁধের উপর নজর রাখতে পারেন ইন্টারনেট যদিও আপনি কীভাবে জানেন যে আমি অনুসন্ধান করি নি? অপেক্ষা না বলুন! তুমি ঠিক দেখেছ? আমার বক্তব্য।
ইউস্টমে

5
একটি প্রশ্ন জিজ্ঞাসা একটি অনুসন্ধান করার চেয়ে বেশি সময় ব্যয়। পরের বার কেবল 'সে / সে' অনুসন্ধান বা 10 করেছিল বলে অনুমান করুন
ইউস্টমে

2
এটি এখনও বেশ খানিকটা দৃষ্টি আকর্ষণ করে, তাই আমি ভেবেছিলাম যে আমি উল্লেখ করব যে রিসার্পার এমন জায়গাগুলি প্রস্তাব করার ক্ষেত্রে খুব ভাল কাজ করে যেখানে আপনি পুনরাবৃত্ত কোডগুলিকে লিনকিউ বিবৃতিতে রূপান্তর করতে পারেন। লিনকিউতে নতুন লোকের পক্ষে এই উদ্দেশ্যে একা থাকা এটি একটি অনিবার্য সরঞ্জাম হতে পারে।
ইয়াক

উত্তর:


206

আপনি এটি Contains()জন্য ব্যবহার করতে পারেন । আপনি যখন সত্যিই কোনও INধারাটি তৈরি করার চেষ্টা করছেন তখন এটি কিছুটা পিছনের দিকে অনুভূত হবে তবে এটি করা উচিত:

var userProfiles = _dataContext.UserProfile
                               .Where(t => idList.Contains(t.Id));

আমি আরও ধরে নিচ্ছি যে প্রতিটি UserProfileরেকর্ডের একটি int Idক্ষেত্র থাকবে to যদি এটি না হয় তবে আপনাকে সে অনুযায়ী সামঞ্জস্য করতে হবে।


হাই, হ্যাঁ ব্যবহারকারী প্রোফাইলে রেকর্ডগুলিতে আইডি রয়েছে। তাই কোনওভাবে আমি t => t.id == idList.Contains (id) এর মতো কিছু করব?
ইউস্টমে

Contains()আমি উত্তরটিতে idযেমন লিখেছি আপনি যদি এটি ব্যবহার করেন তবে প্রতিটি মানের সেই সাম্যতা পরীক্ষা করতে পারবেন। আপনি ==যখন কোনও সেট (অ্যারে) এর আইটেমিকে অন্য (ডাটাবেস টেবিল) এর সাথে তুলনা করার চেষ্টা করছেন তখন আপনাকে স্পষ্টভাবে কোথাও লিখতে হবে না ।
ইয়াক

সমস্যাটি হ'ল টি ব্যবহারকারীর প্রোফাইলে পুরো বস্তুটি ধারণ করে এবং আইডলিস্টে কেবল ইনট থাকে। সংকলকটি কিছু সম্পর্কে অভিযোগ করেছে তবে আমি এটি ঠিক করতে পেরেছি। ধন্যবাদ।
ইউস্টমে

1
@ ইয়াক - আমার পক্ষে কাজ করে না, বলে ফাংশনটির সময়সীমা শেষ! অলস লোডিং অক্ষম করেছে কিন্তু এখনও ব্যর্থ হয়।
ভুভিন

1
আমি "ল্যাম্বডা এক্সপ্রেশনটিকে 'ইনট' টাইপ করতে রূপান্তর করতে পারি না কারণ এটি কোনও প্রতিনিধি প্রকার নয়। কীভাবে ঠিক করব?
স্টিথান

90

সমাধান। কোথায় এবং। কনটেইনসে ও (এন স্কোয়ার) এর জটিলতা রয়েছে। সরল .জয়িনের আরও ভাল পারফরম্যান্স হওয়া উচিত (হ্যাশিংয়ের কারণে ও (এন) এর কাছাকাছি)। সুতরাং সঠিক কোডটি হ'ল:

_dataContext.UserProfile.Join(idList, up => up.ID, id => id, (up, id) => up);

এবং এখন আমার পরিমাপের ফলাফল। আমি 100 000 ব্যবহারকারীর প্রোফাইল এবং 100 000 আইডি তৈরি করেছি generated যোগদানের সময়টি 32 মিমি এবং। যেখানেই ছিল। কন্টেন্টগুলি 2 মিনিট 19 সেকেন্ড সময় নিয়েছিল! আমি আমার বক্তব্য প্রমাণের জন্য এই পরীক্ষার জন্য খাঁটি আইনিংরেবল ব্যবহার করেছি। আপনি যদি সংখ্যার পরিবর্তে তালিকাটি ব্যবহার করেন তবে। কোথায় এবং। কনটেনগুলি আরও দ্রুত হবে। যাইহোক পার্থক্য উল্লেখযোগ্য। দ্রুততম .যেহেতু। কনটেন্টস সেট <> সাথে রয়েছে। এটি সমস্ত .Contains এর জন্য অন্তর্নিহিত coletions জটিলতার উপর নির্ভর করে। লিনক জটিলতা সম্পর্কে জানতে এই পোস্টটি দেখুন below নীচে আমার পরীক্ষার নমুনা দেখুন:

    private static void Main(string[] args)
    {
        var userProfiles = GenerateUserProfiles();
        var idList = GenerateIds();
        var stopWatch = new Stopwatch();
        stopWatch.Start();
        userProfiles.Join(idList, up => up.ID, id => id, (up, id) => up).ToArray();
        Console.WriteLine("Elapsed .Join time: {0}", stopWatch.Elapsed);
        stopWatch.Restart();
        userProfiles.Where(up => idList.Contains(up.ID)).ToArray();
        Console.WriteLine("Elapsed .Where .Contains time: {0}", stopWatch.Elapsed);
        Console.ReadLine();
    }

    private static IEnumerable<int> GenerateIds()
    {
       // var result = new List<int>();
        for (int i = 100000; i > 0; i--)
        {
            yield return i;
        }
    }

    private static IEnumerable<UserProfile> GenerateUserProfiles()
    {
        for (int i = 0; i < 100000; i++)
        {
            yield return new UserProfile {ID = i};
        }
    }

কনসোল আউটপুট:

অতিবাহিত .জমিন সময়: 00: 00: 00.0322546

অতিবাহিত .কখন। সময় রয়েছে: 00: 02: 19.4072107


4
আপনি কি সংখ্যা দিয়ে এই ব্যাক আপ করতে পারেন?
ইউস্টমে

ভাল, যাইহোক আমাকে কৌতূহলী করে তোলে যখন Listব্যবহৃত হয় সময়গুলি কি হবে । +1
Yustme

ঠিক আছে, আপনি আগ্রহী এমন সময় এখানে রইল: তালিকায় 13.1 সেকেন্ড সময় লেগেছে এবং হ্যাশসেটটি 0,7 এমএস নিয়েছে! সুতরাং .যেখানে। কনটেন্টগুলি কেবল হ্যাশসেটের ক্ষেত্রেই সেরা (যখন। কনটেইনগুলিতে জটিলতা ও (1)) থাকে। অন্যান্য ক্ষেত্রে, .জয়েন আরও ভাল
ডেভিড গ্রেগর

5
আমি Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator.লিনকিউ 2 এসকিউএল ডেটাঅন্টেক্সট ব্যবহার করার সময় ত্রুটি পেয়েছি।
মায়াঙ্ক রায়চুরা

3
@ ইউস্টমে - পারফরম্যান্স সর্বদা বিবেচ্য। (আমি "এটি গ্রহণযোগ্য উত্তর হওয়া উচিত" লোক হিসাবে ঘৃণা করি, তবে ...)

19

দুর্দান্ত উত্তরগুলি নীচে, তবে একটি গুরুত্বপূর্ণ জিনিসটি ভুলে যাবেন না - তারা বিভিন্ন ফলাফল সরবরাহ করে!

  var idList = new int[1, 2, 2, 2, 2]; // same user is selected 4 times
  var userProfiles = _dataContext.UserProfile.Where(e => idList.Contains(e)).ToList();

এটি ডিবি থেকে ২ টি সারি ফিরিয়ে দেবে (এবং এটি সঠিক হতে পারে, যদি আপনি কেবল ব্যবহারকারীদের একটি পৃথক বাছাই করা তালিকা চান)

তবে অনেক ক্ষেত্রেই, আপনি ফলাফলের একটি অরসেটেড তালিকা চাইতে পারেন । আপনার সবসময় এসকিউএল কোয়েরির মতো এটি সম্পর্কে ভাবতে হবে। কী চলছে তা বোঝাতে দয়া করে ইশপ শপিং কার্ট সহ উদাহরণটি দেখুন:

  var priceListIDs = new int[1, 2, 2, 2, 2]; // user has bought 4 times item ID 2
  var shoppingCart = _dataContext.ShoppingCart
                     .Join(priceListIDs, sc => sc.PriceListID, pli => pli, (sc, pli) => sc)
                     .ToList();

এটি ডিবি থেকে 5 টি ফলাফল ফিরিয়ে দেবে। এই ক্ষেত্রে 'রয়েছে' ব্যবহার করা ভুল হবে।


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