ডেটা রিডার থেকে ডেটা টেবিলটি পপুলেট করুন


103

আমি সি # (এমএস ভিএস ২০০৮) এ একটি বেসিক কাজ করছি এবং নির্দিষ্ট কোডের চেয়ে সঠিক নকশা সম্পর্কে আরও একটি প্রশ্ন আছে।

আমি একটি ডেটাতেবল তৈরি করছি এবং তারপরে একটি ডেটারেডার (যা একটি এসকিউএল সঞ্চিত পদ্ধতির উপর ভিত্তি করে) থেকে ডেটাটিবল লোড করার চেষ্টা করছি। আমি যা ভাবছি তা হ'ল ডেটাটেবল লোড করার সবচেয়ে কার্যকরী উপায় হ'ল কিছুক্ষণ বিবৃতি দেওয়া, বা যদি আরও ভাল উপায় থাকে।

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

আমি যা করি তার সম্পূর্ণতার নীচে কোড স্নিপেটগুলি অন্তর্ভুক্ত করেছি, যদিও কোডটি নিজেই অসাধারণ নয় এমনকি আমি যা জিজ্ঞাসা করছি তা নয়। মোরেসো আমার পদ্ধতি সম্পর্কে ভাবছেন, আমার কৌশলটি যদি ভুল / অকার্যকর হয় তবে আমি পরে কোডের সাহায্যের জন্য পেস্টার করব।

var dtWriteoffUpload = new DataTable();
dtWriteoffUpload.Columns.Add("Unit");
dtWriteoffUpload.Columns.Add("Year");
dtWriteoffUpload.Columns.Add("Period");
dtWriteoffUpload.Columns.Add("Acct");
dtWriteoffUpload.Columns.Add("Descr");
dtWriteoffUpload.Columns.Add("DEFERRAL_TYPE");
dtWriteoffUpload.Columns.Add("NDC_Indicator");
dtWriteoffUpload.Columns.Add("Mgmt Cd");
dtWriteoffUpload.Columns.Add("Prod");
dtWriteoffUpload.Columns.Add("Node");
dtWriteoffUpload.Columns.Add("Curve_Family");
dtWriteoffUpload.Columns.Add("Sum Amount");
dtWriteoffUpload.Columns.Add("Base Curr");
dtWriteoffUpload.Columns.Add("Ledger");  

cmd = util.SqlConn.CreateCommand();
cmd.CommandTimeout = 1000;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "proc_writeoff_data_details";
cmd.Parameters.Add("@whoAmI", SqlDbType.VarChar).Value = 

WindowsIdentity.GetCurrent().Name;

cmd.Parameters.Add("@parmEndDateKey", SqlDbType.VarChar).Value = myMostRecentActualDate;
cmd.Parameters.Add("@countrykeys", SqlDbType.VarChar).Value = myCountryKey;
cmd.Parameters.Add("@nodekeys", SqlDbType.VarChar).Value = "1,2";
break;


dr = cmd.ExecuteReader();
while (dr.Read())                    
{
    dtWriteoffUpload.Rows.Add(dr["country name"].ToString(), dr["country key"].ToString());
}

ডুপ্লিকেট প্রশ্ন: stackoverflow.com/questions/4089471/...
vapcguy

উত্তর:


283

আপনি গ্রহণযোগ্য পদ্ধতিটি DataTableব্যবহার করে কোনও ডেটা রিডার থেকে সরাসরি লোড করতে পারেন ।Load()IDataReader

var dataReader = cmd.ExecuteReader();
var dataTable = new DataTable();
dataTable.Load(dataReader);

2
আপনি আমার দিন (Y)
উজায়ের এক্সলেড

1
আমি এই এক সন্ধানের জন্য এক সপ্তাহ কাটিয়েছি!
দ্য টেকি

17

নীচের কোডটি চেক করুন। স্বয়ংক্রিয়ভাবে এটি ডেটা টেবিল হিসাবে রূপান্তরিত হবে

private void ConvertDataReaderToTableManually()
    {
        SqlConnection conn = null;
        try
        {
            string connString = ConfigurationManager.ConnectionStrings["NorthwindConn"].ConnectionString;
            conn = new SqlConnection(connString);
            string query = "SELECT * FROM Customers";
            SqlCommand cmd = new SqlCommand(query, conn);
            conn.Open();
            SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            DataTable dtSchema = dr.GetSchemaTable();
            DataTable dt = new DataTable();
            // You can also use an ArrayList instead of List<>
            List<DataColumn> listCols = new List<DataColumn>();

            if (dtSchema != null)
            {
                foreach (DataRow drow in dtSchema.Rows)
                {
                    string columnName = System.Convert.ToString(drow["ColumnName"]);
                    DataColumn column = new DataColumn(columnName, (Type)(drow["DataType"]));
                    column.Unique = (bool)drow["IsUnique"];
                    column.AllowDBNull = (bool)drow["AllowDBNull"];
                    column.AutoIncrement = (bool)drow["IsAutoIncrement"];
                    listCols.Add(column);
                    dt.Columns.Add(column);
                }
            }

            // Read rows from DataReader and populate the DataTable
            while (dr.Read())
            {
                DataRow dataRow = dt.NewRow();
                for (int i = 0; i < listCols.Count; i++)
                {
                    dataRow[((DataColumn)listCols[i])] = dr[i];
                }
                dt.Rows.Add(dataRow);
            }
            GridView2.DataSource = dt;
            GridView2.DataBind();
        }
        catch (SqlException ex)
        {
            // handle error
        }
        catch (Exception ex)
        {
            // handle error
        }
        finally
        {
            conn.Close();
        }

    }

ডেটাএডেডিটারে ডেটারিয়েডার লোড করার জন্য একটি সরাসরি ফরোয়ার্ড বিকল্প রয়েছে, তবে কেন কেউ এটি ব্যবহার করবে?
আব্বাস

@ সরথকুমার ভাল কাজ .. আমি এই জাতীয় কোড
খুঁজছিলাম

@ আব্বাস কোজ, ইনবিল্ট ডেটা লোড খুব ধীর
সিম্পলগুই

dt.Load(reader)এছাড়াও সবসময় কাজ করে না - আমি এই Object reference not set to an instance of an objectসমস্যাগুলি ত্রুটিগুলি পেয়েছিলাম সম্ভবত আমি যখন কোনও সারি ফিরে না পাই। এর মতো কিছু ম্যানুয়াল হাতে আসে। আমি এটা চেষ্টা এবং যারা পরিত্রাণ পেতে ছিল column.লাইন dtSchema foreachলুপ কারণ বলা এটি একটি অবৈধ অভিনেতা ছিল boolউপর (bool)drow["IsUnique"]। আমার তাদের দরকার নেই, নতুনটি তৈরির DataTableজন্য কলামের নামগুলি পাওয়া যথেষ্ট। এটি আমাকে এমন কোনও ds.Fill(adapter)সমস্যা কাটিয়ে উঠতে সহায়তা করেছে যেখানে আমি বড় টেবিলটি লোড করতে পারি না SELECT * FROM MyTable
vapcguy

একটি সতর্কতামূলক - যদি কোনও কলামে নাল মান থাকে তবে সেগুলি পরিচালনা করতে হবে বা এই ফাংশনটি ব্যতিক্রম ঘটায়। if (!dr.IsDBNull(i))যে forলুপ ভিতরে পরবর্তী জিনিস হিসাবে চেক করতে হবে । আপনি তারপর আপনার dataRowজিনিস না। তবে তারপরে আপনার একটি দরকার else, যদি আপনি কোনও শূন্যতা পান। যদি আপনি না, আপনি কলাম আপনি যোগ করছি ধরণ জিনিসটা আছে, এবং সেই অনুযায়ী নাল নির্ধারণ (অর্থাত আপনি ধার্য করতে পারেন String.Emptyযদি এটা ধরনের এর System.String, কিন্তু আপনি দায়িত্ব অর্পণ করা আছে 0যদি এটা System.Int16(বুলিয়ান ক্ষেত্র) অথবা System.Decimal
vapcguy

13

যদি আপনি একটি লোড করার চেষ্টা করছেন DataTableতবে এর SqlDataAdapterপরিবর্তে উত্তোলন করুন :

DataTable dt = new DataTable();

using (SqlConnection c = new SqlConnection(cString))
using (SqlDataAdapter sda = new SqlDataAdapter(sql, c))
{
    sda.SelectCommand.CommandType = CommandType.StoredProcedure;
    sda.SelectCommand.Parameters.AddWithValue("@parm1", val1);
    ...

    sda.Fill(dt);
}

এমনকি কলামগুলি সংজ্ঞায়িত করার দরকার নেই। শুধু DataTableএবং Fillএটি তৈরি করুন ।

এখানে, cStringআপনার সংযোগের স্ট্রিং এবং sqlএটি সঞ্চিত পদ্ধতি কমান্ড।


1
এখানে কেবল সমস্যাটি হ'ল যদি আপনি কোনও কলাম / মান পূরণের সময় একটি ব্যতিক্রম ঘটায় তবে এটি আপনাকে কোনও বিশদ দেয় না, যেমন আপনি SqlDataReaderক্ষেত্রগুলির মধ্যে একটি লুপ ব্যবহার করে এটি ব্যবহার করতে এবং সেগুলি পড়তে সক্ষম হতে পারেন ।
vapcguy

9

যেহেতু সাগি তাদের উত্তরে ডেটা টেবিল বলেছিলেন o লোড একটি ভাল সমাধান। আপনি যদি একক পাঠক থেকে একাধিক টেবিল লোড করার চেষ্টা করছেন তবে আপনাকে DataReader.NextResult কল করতে হবে না। ডেটা টেবিল.লুড পদ্ধতিটি পরবর্তী ফলাফলের সেটটিতে (যদি থাকে) পাঠককেও অগ্রসর করে।

// Read every result set in the data reader.
while (!reader.IsClosed)
{
    DataTable dt = new DataTable();
    // DataTable.Load automatically advances the reader to the next result set
    dt.Load(reader);
    items.Add(dt);
}

5

আমি এটিও সন্ধান করেছি এবং স্ক্ল্যাডেটাডেডিটার.ফিল পদ্ধতিটির সাথে তুলনা করার পরে স্কেলডাটাআরেডার.লুড ফানসিটনের সাথে আমি খুঁজে পেয়েছি যে স্কেলডাটাএডাপ্টার.ফিল পদ্ধতিটি আমি ব্যবহার করছি ফলাফল সেটগুলির দ্বিগুণের চেয়ে দ্রুততর

ব্যবহৃত কোড:

    [TestMethod]
    public void SQLCommandVsAddaptor()
    {
        long AdapterFillLargeTableTime, readerLoadLargeTableTime, AdapterFillMediumTableTime, readerLoadMediumTableTime, AdapterFillSmallTableTime, readerLoadSmallTableTime, AdapterFillTinyTableTime, readerLoadTinyTableTime;

        string LargeTableToFill = "select top 10000 * from FooBar";
        string MediumTableToFill = "select top 1000 * from FooBar";
        string SmallTableToFill = "select top 100 * from FooBar";
        string TinyTableToFill = "select top 10 * from FooBar";

        using (SqlConnection sconn = new SqlConnection("Data Source=.;initial catalog=Foo;persist security info=True; user id=bar;password=foobar;"))
        {
            // large data set measurements
            AdapterFillLargeTableTime = MeasureExecutionTimeMethod(sconn, LargeTableToFill, ExecuteDataAdapterFillStep);
            readerLoadLargeTableTime = MeasureExecutionTimeMethod(sconn, LargeTableToFill, ExecuteSqlReaderLoadStep);
            // medium data set measurements
            AdapterFillMediumTableTime = MeasureExecutionTimeMethod(sconn, MediumTableToFill, ExecuteDataAdapterFillStep);
            readerLoadMediumTableTime = MeasureExecutionTimeMethod(sconn, MediumTableToFill, ExecuteSqlReaderLoadStep);
            // small data set measurements
            AdapterFillSmallTableTime = MeasureExecutionTimeMethod(sconn, SmallTableToFill, ExecuteDataAdapterFillStep);
            readerLoadSmallTableTime = MeasureExecutionTimeMethod(sconn, SmallTableToFill, ExecuteSqlReaderLoadStep);
            // tiny data set measurements
            AdapterFillTinyTableTime = MeasureExecutionTimeMethod(sconn, TinyTableToFill, ExecuteDataAdapterFillStep);
            readerLoadTinyTableTime = MeasureExecutionTimeMethod(sconn, TinyTableToFill, ExecuteSqlReaderLoadStep);
        }
        using (StreamWriter writer = new StreamWriter("result_sql_compare.txt"))
        {
            writer.WriteLine("10000 rows");
            writer.WriteLine("Sql Data Adapter 100 times table fill speed 10000 rows: {0} milliseconds", AdapterFillLargeTableTime);
            writer.WriteLine("Sql Data Reader 100 times table load speed 10000 rows: {0} milliseconds", readerLoadLargeTableTime);
            writer.WriteLine("1000 rows");
            writer.WriteLine("Sql Data Adapter 100 times table fill speed 1000 rows: {0} milliseconds", AdapterFillMediumTableTime);
            writer.WriteLine("Sql Data Reader 100 times table load speed 1000 rows: {0} milliseconds", readerLoadMediumTableTime);
            writer.WriteLine("100 rows");
            writer.WriteLine("Sql Data Adapter 100 times table fill speed 100 rows: {0} milliseconds", AdapterFillSmallTableTime);
            writer.WriteLine("Sql Data Reader 100 times table load speed 100 rows: {0} milliseconds", readerLoadSmallTableTime);
            writer.WriteLine("10 rows");
            writer.WriteLine("Sql Data Adapter 100 times table fill speed 10 rows: {0} milliseconds", AdapterFillTinyTableTime);
            writer.WriteLine("Sql Data Reader 100 times table load speed 10 rows: {0} milliseconds", readerLoadTinyTableTime);

        }
        Process.Start("result_sql_compare.txt");
    }

    private long MeasureExecutionTimeMethod(SqlConnection conn, string query, Action<SqlConnection, string> Method)
    {
        long time; // know C#
        // execute single read step outside measurement time, to warm up cache or whatever
        Method(conn, query);
        // start timing
        time = Environment.TickCount;
        for (int i = 0; i < 100; i++)
        {
            Method(conn, query);
        }
        // return time in milliseconds
        return Environment.TickCount - time;
    }

    private void ExecuteDataAdapterFillStep(SqlConnection conn, string query)
    {
        DataTable tab = new DataTable();
        conn.Open();
        using (SqlDataAdapter comm = new SqlDataAdapter(query, conn))
        {
            // Adapter fill table function
            comm.Fill(tab);
        }
        conn.Close();
    }

    private void ExecuteSqlReaderLoadStep(SqlConnection conn, string query)
    {
        DataTable tab = new DataTable();
        conn.Open();
        using (SqlCommand comm = new SqlCommand(query, conn))
        {
            using (SqlDataReader reader = comm.ExecuteReader())
            {
                // IDataReader Load function
                tab.Load(reader);
            }
        }
        conn.Close();
    }

ফলাফল:

10000 rows:
Sql Data Adapter 100 times table fill speed 10000 rows: 11782 milliseconds
Sql Data Reader  100 times table load speed 10000 rows: 26047 milliseconds
1000 rows:
Sql Data Adapter 100 times table fill speed 1000 rows: 984  milliseconds
Sql Data Reader  100 times table load speed 1000 rows: 2031 milliseconds
100 rows:
Sql Data Adapter 100 times table fill speed 100 rows: 125 milliseconds
Sql Data Reader  100 times table load speed 100 rows: 235 milliseconds
10 rows:
Sql Data Adapter 100 times table fill speed 10 rows: 32 milliseconds
Sql Data Reader  100 times table load speed 10 rows: 93 milliseconds

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

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