সি # তে স্কেলডেটাআরডিডার ব্যবহার করে কীভাবে সারিগুলির সংখ্যা পাবেন?


98

আমার প্রশ্ন হ'ল SqlDataReaderসি # তে কীভাবে কোনও ক্যোয়ারী দিয়ে ফিরে আসা সারিগুলির সংখ্যা পাবেন । আমি এই সম্পর্কে কিছু উত্তর দেখেছি তবে কোনওটি ছাড়াই স্পষ্টভাবে সংজ্ঞায়িত করা হয়েছিল যা Read()পদ্ধতি এবং বর্ধিত কাউন্টারটির সাথে কিছুক্ষণ লুপ করতে বলে ।

আমার সমস্যাটি হ'ল আমি প্রথম সারিতে কলাম শিরোনামের নাম এবং তার পরে প্রতিটি সারিতে সারি ডেটা হওয়ার সাথে একটি বহুমাত্রিক অ্যারে পূরণ করার চেষ্টা করছি।

আমি জানি যে আমি কেবল তালিকা নিয়ন্ত্রণে স্টাফগুলিকে ডাম্প করতে পারি এবং এটি সম্পর্কে উদ্বিগ্ন হওয়ার দরকার নেই, তবে নিজের ব্যক্তিগত উত্সাহের জন্য এবং আমি পছন্দ করে নেওয়ার সাথে সাথে অ্যারের বাইরেও তথ্য টানতে এবং এটিকে বিভিন্ন ফর্ম্যাটে প্রদর্শন করতে চাই।

সুতরাং আমি মনে করি আমি Read()এবং তারপরে ইনক্রিমেন্টটি ++ উপায় করতে পারি না কারণ এর অর্থ হল যে সারিগুলির পরিমাণ এবং তারপরে কলামের ডেটা পেতে আমাকে আবার Read()খুলতে হবে এবং তারপরে Read()আবার খুলতে হবে।

আমি যা বলছি তার একটি ছোট্ট উদাহরণ:

int counter = 0;    

while (sqlRead.Read())
{
    //get rows
    counter++
}

এবং তারপরে কলামগুলি এবং পপগুলির মধ্য দিয়ে চলার জন্য লুপের জন্য একটি

something.Read();

int dbFields = sqlRead.FieldCount;

for (int i = 0; i < dbFields; i++)
{
   // do stuff to array
}

উত্তর:


97

দুটি মাত্র বিকল্প রয়েছে:

  • সমস্ত সারি পড়ে অনুসন্ধান করুন (এবং তারপরে আপনি এগুলি সংরক্ষণও করতে পারেন)

  • আগেই একটি বিশেষায়িত নির্বাচন COUNT (*) কোয়েরি চালান।

ডেটা রিডার লুপের মধ্য দিয়ে দু'বার যাওয়া সত্যিই ব্যয়বহুল, আপনাকে কোয়েরিটি পুনরায় সম্পাদন করতে হবে।

এবং (পিট ওহানলোনকে ধন্যবাদ) দ্বিতীয় বিকল্পটি কেবল সম্মতি-নিরাপদ যখন আপনি স্ন্যাপশট বিচ্ছিন্নতা স্তরের সাথে কোনও লেনদেন ব্যবহার করেন।

যেহেতু আপনি যে কোনওভাবেই সমস্ত সারি মেমরিতে সঞ্চয় করতে চান কেবল একমাত্র বুদ্ধিমান বিকল্প হ'ল সমস্ত সারিগুলি একটি নমনীয় স্টোরেজ ( List<>বা DataTable) এ পড়ুন এবং তারপরে আপনার পছন্দ মতো যে কোনও ফর্ম্যাটে ডেটা অনুলিপি করুন। ইন-মেমরি অপারেশন সর্বদা আরও কার্যকর হবে।


4
হেন্ক ঠিক বলেছেন: ডেটা রিডারটির কোনও সদস্য নেই যা আপনাকে সারিগুলির সংখ্যা পেতে দেয় কারণ এটি কেবলমাত্র একমাত্র পাঠক। আপনি প্রথমে গণনা করা এবং তারপরে কোয়েরিটি কার্যকর করার চেয়ে আরও ভাল, সম্ভবত কোনও বহু-ফলাফলের ক্যোয়ারিতে যাতে আপনি কেবল একবার ডাটাবেসটিকে হিট করেন।
ফ্লিপডাব্ট

14
বিশেষায়িত গণনাতে সমস্যাটি হ'ল গণনা প্রত্যাবর্তনকৃত সারিগুলির সংখ্যার চেয়ে আলাদা হওয়ার সম্ভাবনা রয়েছে কারণ অন্য কেউ ডেটা এমনভাবে পরিবর্তন করেছে যাতে সারিগুলির সংখ্যা ফিরে আসে।
পিট ওহানলন

4
পিট, আপনি ঠিক বলেছেন, এটির জন্য একটি ব্যয়বহুল আইসোলেশন লেভেল প্রয়োজন।
হেন্ক হলটারম্যান

4
সবাইকে ধন্যবাদ! এটি আরও স্পষ্ট হয়ে উঠছে। তাহলে কী ডেটাসেটে সমস্ত তথ্য ফেলে দেওয়া বা কোনও এসকিউএল COUNT (*) এর মাধ্যমে চালানো, এটি সঞ্চয় করে তারপরে প্রয়োজনীয় কোয়েরি চালানো ভাল? বা আমরা ডেটাসেটে গণনা চালানো এবং সবকিছু সংরক্ষণ করার কথা বলছি?
টমাসজ ইনিউইচিজ

4
একটি RepeatableReadবিচ্ছিন্নতা স্তর পরিসীমা-লকিং সম্পাদন করে না তাই এটি এখনও রেকর্ড সন্নিবেশ করতে দেয়, আপনাকে Snapshotবা এর বিচ্ছিন্নতা স্তর ব্যবহার করা দরকার Serializable
লুকুয়েড

10

আপনার যদি সমস্ত সারিটি পুনরুদ্ধার করার প্রয়োজন না হয় এবং একটি ডাবল ক্যোয়ারী করা এড়াতে চান তবে আপনি সম্ভবত এরকম কিছু চেষ্টা করতে পারেন:

using (var sqlCon = new SqlConnection("Server=127.0.0.1;Database=MyDb;User Id=Me;Password=glop;"))
      {
        sqlCon.Open();

        var com = sqlCon.CreateCommand();
        com.CommandText = "select * from BigTable";
        using (var reader = com.ExecuteReader())
        {
            //here you retrieve what you need
        }

        com.CommandText = "select @@ROWCOUNT";
        var totalRow = com.ExecuteScalar();

        sqlCon.Close();
      }

একই কমান্ডটি পুনরায় ব্যবহার করা হলে এতে স্বয়ংক্রিয়ভাবে কোনও লেনদেন যুক্ত হবে কিনা তা নিশ্চিত না করে আপনাকে কোনও লেনদেন যুক্ত করতে হতে পারে ...


4
যে কেউ বলতে পারে যদি @@ ROWCOUNT সর্বদা উপরের উপরের সর্বশেষ ক্যোয়ারির উপর নির্ভর করে? সমস্যাগুলি যদি অনেক সংযোগ সমান্তরালভাবে ক্যোয়ারী চালায়?
YvesR

4
এটা করা দরকার sqlCon.Close();? আমি ভেবেছিলাম যে usingএটি আপনার জন্য করা উচিত।
নীলাভ

4
পাঠকের কাছ থেকে তথ্য পুনরুদ্ধার করার আগে যখন আমাদের সারসংক্ষেপের প্রয়োজন হবে তখন তা কার্যকর হবে না
হিমানশু ভাল্লা

8

উপরের হিসাবে, একটি ডেটাসেট বা টাইপ করা ডেটাসেট একটি ভাল টেমোরারি কাঠামো হতে পারে যা আপনি আপনার ফিল্টারিংয়ের জন্য ব্যবহার করতে পারেন। একটি স্কেলডাটাআরডার মানে খুব দ্রুত ডেটা পড়তে হয়। আপনি যখন () লুপটিতে রয়েছেন তখনও আপনি ডিবির সাথে সংযুক্ত রয়েছেন এবং পরবর্তী ফলাফলটি পড়ার আগে এটি প্রক্রিয়া করার জন্য আপনি যা কিছু করছেন তা আপনার জন্য অপেক্ষা করছে। এক্ষেত্রে আপনি যদি সমস্ত ডেটা টানেন, ডিবির সাথে সংযোগ বন্ধ করেন এবং ফলাফলগুলি "অফলাইন" প্রসেস করেন তবে আপনি আরও ভাল পারফরম্যান্স পেতে পারেন।

লোকেরা ডেটাসেটগুলিকে ঘৃণা করে বলে মনে হয়, সুতরাং উপরেরগুলি দৃ strongly়ভাবে টাইপ করা সামগ্রীর সংকলন সহ সম্পন্ন করা যেতে পারে।


4
আমি ডেটাসেটগুলি নিজেরাই পছন্দ করি, যেহেতু তারা টেবিল-ভিত্তিক ডেটার একটি লিখিত এবং অত্যন্ত দরকারী জেনেরিক উপস্থাপনা। অদ্ভুতভাবে যথেষ্ট, আমি লক্ষ্য করেছি যে ওআরএম-এর জন্য ডেটাসেট বন্ধ করা বেশিরভাগ লোকেরা একই ব্যক্তি যারা নিজের কোডটি লেখার চেষ্টা করেন যতটা সম্ভব জেনেরিক (সাধারণত অর্থহীন)।
মুসিজেনেসিস

4
ড্যানিয়েল, 'উপরে' অন্য উত্তরটি উল্লেখ করার পক্ষে ভাল উপায় নয়।
হেন্ক হলটারম্যান

6

আপনি সরাসরি ডেটা পাঠকের কাছ থেকে সারিগুলির একটি গণনা পেতে পারেন না কারণ এটি যা ফায়ার হুজ কার্সার হিসাবে পরিচিত which যার অর্থ এই যে পড়াটি সঞ্চালনের ভিত্তিতে সারি ভিত্তিতে ডেটা সারি ভিত্তিতে পড়ে। আমি ডেটাতে 2 টি পড়ার বিরুদ্ধে পরামর্শ দেব কারণ 2 রিডের মধ্যে ডেটা পরিবর্তনের সম্ভাবনা রয়েছে এবং তাই আপনি বিভিন্ন ফলাফল পেতে পারেন।

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


5

পিট উত্তরটি সম্পূর্ণ করতে এবং আরও ভাল পারফরম্যান্সের জন্য: সমস্তই একটি ক্যোয়ারিতে পান এবং NextResult পদ্ধতিটি ব্যবহার করুন।

using (var sqlCon = new SqlConnection("Server=127.0.0.1;Database=MyDb;User Id=Me;Password=glop;"))
{
    sqlCon.Open();
    var com = sqlCon.CreateCommand();
    com.CommandText = "select * from BigTable;select @@ROWCOUNT;";
    using (var reader = com.ExecuteReader())
    {
        while(reader.read()){
            //iterate code
        }
        int totalRow = 0 ;
        reader.NextResult(); // 
        if(reader.read()){
            totalRow = (int)reader[0];
        }
    }
    sqlCon.Close();
}

1

আমি যখন একটি শীর্ষের ফলাফল ফেরত দেওয়ার প্রয়োজন তখনও আমি এমন পরিস্থিতির মুখোমুখি হয়েছি যেখানে কোয়েরির সাথে মিল থাকা মোট সারিও পেতে চেয়েছিলাম। আমি চূড়ান্তভাবে এই সমাধান পেতে:

   public string Format(SelectQuery selectQuery)
    {
      string result;

      if (string.IsNullOrWhiteSpace(selectQuery.WherePart))
      {
        result = string.Format(
@"
declare @maxResult  int;
set @maxResult = {0};

WITH Total AS
(
SELECT count(*) as [Count] FROM {2}
)
SELECT top (@maxResult) Total.[Count], {1} FROM Total, {2}", m_limit.To, selectQuery.SelectPart, selectQuery.FromPart);
      }
      else
      {
        result = string.Format(
@"
declare @maxResult  int;
set @maxResult = {0};

WITH Total AS
(
SELECT count(*) as [Count] FROM {2} WHERE {3}
)
SELECT top (@maxResult) Total.[Count], {1} FROM Total, {2} WHERE {3}", m_limit.To, selectQuery.SelectPart, selectQuery.FromPart, selectQuery.WherePart);
      }

      if (!string.IsNullOrWhiteSpace(selectQuery.OrderPart))
        result = string.Format("{0} ORDER BY {1}", result, selectQuery.OrderPart);

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