ডেটা টেবিল থেকে নির্দিষ্ট সারি মুছে ফেলা হচ্ছে


87

আমি ডেটা টেবিল থেকে কিছু সারি মুছতে চাই, তবে এটি এর মতো একটি ত্রুটি দেয়,

সংগ্রহটি পরিবর্তন করা হয়েছিল; গণনা ক্রিয়াকলাপ চালানো হতে পারে না

আমি এই কোডটি মুছে ফেলার জন্য ব্যবহার করি,

foreach(DataRow dr in dtPerson.Rows){
    if(dr["name"].ToString()=="Joe")
        dr.Delete();
}

সুতরাং, সমস্যা কী এবং কীভাবে এটি ঠিক করবেন? আপনি কোন পদ্ধতির পরামর্শ দিচ্ছেন?

উত্তর:


170

আপনি যদি কোনও সংগ্রহ থেকে কোনও আইটেম মুছে ফেলেন তবে সেই সংগ্রহটি পরিবর্তন করা হয়েছে এবং আপনি এটির মাধ্যমে অঙ্কটি চালিয়ে যেতে পারবেন না।

পরিবর্তে, একটি লুপ ব্যবহার করুন, যেমন:

for(int i = dtPerson.Rows.Count-1; i >= 0; i--)
{
    DataRow dr = dtPerson.Rows[i];
    if (dr["name"] == "Joe")
        dr.Delete();
}
dtPerson.AcceptChanges();

নোট করুন যে আপনি বর্তমান সূচকটি মোছার পরে কোনও সারি এড়ানো এড়াতে বিপরীতে পুনরাবৃত্তি করছেন।


@ স্লাগস্টার আমাকে এতে মারধর করেছেন! (আমি আপনার স্বনির্বাচিত [ii]করতে [i]অবশ্য :-)
Widor

11
এটি ভুল। আপনি করতে পারেন সারি মোছার সময় একটি টেবিল মাধ্যেমে লুপ করতে একটি foreach ব্যবহার করুন। স্টিভ উত্তর দেখুন ।
আলেকজান্ডার গার্ডেন

4
এই উত্তরটিতে @ বোকির উত্তর অন্তর্ভুক্ত করা উচিত। আমরা যদি DataTableপরে ব্যবহার করি তবে এর ব্যতিক্রম একটি ব্যতিক্রম। সঠিক Remove()উপায়টি হ'ল উত্সটিতে কল করা DataTable- dtPerson.Rows.Remove(dr)
Code.me

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

মোছা কার্যকর হওয়ার জন্য Delete()কল ব্যবহার করার প্রয়োজন নেই AcceptChanges()?
ব্রুটস ওয়েম্ব

128

প্রত্যেকে 'এনুমুরেশন সারিগুলি মুছে ফেলতে পারবেন না ' ব্যান্ডওয়াগনে লাফ দেওয়ার আগে আপনাকে প্রথমে উপলব্ধি করতে হবে যে ডেটা টেবিলগুলি লেনদেনের , এবং যতক্ষণ না আপনি অ্যাকસેপট চেঞ্জস () কল করবেন ততক্ষণ প্রযুক্তিগতভাবে পরিবর্তনগুলি পরিষ্কার করবেন না )

আপনি যদি মুছে ফেলতে কল করার সময় এই ব্যতিক্রমটি দেখছেন , আপনি ইতিমধ্যে একটি মুলতুবি-পরিবর্তন ডেটা স্থিতিতে রয়েছেন । উদাহরণস্বরূপ, আপনি যদি ডাটাবেস থেকে সবেমাত্র লোড করেছেন, মুছে ফেলা কলটি একটি ফোরচ লুপের ভিতরে থাকলে একটি ব্যতিক্রম ছুঁড়ে মারবে।

কিন্তু! কিন্তু!

আপনি যদি ডাটাবেস থেকে সারিগুলি লোড করেন এবং ফাংশনটিকে ' AcceptChanges () ' বলে কল করেন আপনি ডেটা টেবেলে এই সমস্ত মুলতুবি পরিবর্তনগুলি প্রতিশ্রুতিবদ্ধ। এখন আপনি বিশ্বের কোনও যত্ন ছাড়াই মুছে ফেলা () মুছে ফেলার সারিগুলির তালিকাটির মাধ্যমে পুনরাবৃত্তি করতে পারেন, কারণ এটি মুছে ফেলার জন্য সারিটি কানের চিহ্ন দেয়, তবে যতক্ষণ না আপনি পুনরায় AcceptChanges () কল না করেন ততক্ষণ প্রতিশ্রুতিবদ্ধ না is

আমি বুঝতে পারি যে এই প্রতিক্রিয়াটি কিছুটা তারিখের, তবে সম্প্রতি একটি অনুরূপ সমস্যা নিয়ে আমার মোকাবিলা করতে হয়েছিল এবং আশা করছি এটি 10 ​​বছরের পুরানো কোডে কাজ করা ভবিষ্যতের বিকাশকারীদের কিছুটা বেদনা বাঁচায় :)


PS এখানে জেফ দ্বারা যুক্ত একটি সহজ কোড উদাহরণ :

সি #

YourDataTable.AcceptChanges(); 
foreach (DataRow row in YourDataTable.Rows) {
    // If this row is offensive then
    row.Delete();
} 
YourDataTable.AcceptChanges();

ভিবি.নেট

ds.Tables(0).AcceptChanges()
For Each row In ds.Tables(0).Rows
    ds.Tables(0).Rows(counter).Delete()
    counter += 1
Next
ds.Tables(0).AcceptChanges()

সি # সংস্করণের জন্য কেবল () এর পরিবর্তে {এবং use ব্যবহার করতে হবে
বাগলভার

4
এছাড়াও আরও সহায়ক (আমার মনে হয়) এ পরিবর্তন object row_loopVariable in ds.Tables(0).RowsকরতেDataRow row in ds.Tables(0).Rows
বাগলওভার

4
এফএফস, এটি দুঃস্বপ্নের সপ্তাহান্তে স্থাপনার সময় আমাকে বাঁচিয়েছে। আপনি সমস্ত বিয়ার প্রাপ্য!
জেমস প্রেমের


চমৎকার কোড। একটা জিনিষ, C # বৃদ্ধিতে টিপিক্যাল পথ এক দ্বারা counter++পরিবর্তে counter+= 1
এমকিউইগজর্জিয়ার

18

এই সমাধান সহ:

for(int i = dtPerson.Rows.Count-1; i >= 0; i--) 
{ 
    DataRow dr = dtPerson.Rows[i]; 
    if (dr["name"] == "Joe")
        dr.Delete();
} 

আপনি যদি সারিটি মোছার পরে ডেটাটেবল ব্যবহার করতে চলেছেন তবে আপনি একটি ত্রুটি পাবেন। তাই কি আপনি কি করতে পারেন: প্রতিস্থাপন dr.Delete();সঙ্গেdtPerson.Rows.Remove(dr);


16

এটি আমার পক্ষে কাজ করে,

List<string> lstRemoveColumns = new List<string>() { "ColValue1", "ColVal2", "ColValue3", "ColValue4" };
List<DataRow> rowsToDelete = new List<DataRow>();

foreach (DataRow row in dt.Rows) {
    if (lstRemoveColumns.Contains(row["ColumnName"].ToString())) {
        rowsToDelete.Add(row);
    }
}

foreach (DataRow row in rowsToDelete) {
    dt.Rows.Remove(row);
}

dt.AcceptChanges();

Dt.AcepceptChanges () মিস করা এত সহজ
ম্যাথু লক

"আপনি মুছে ফেলার জন্য সারি চিহ্নিত করার জন্য ডেটারো ক্লাসের মুছুন পদ্ধতিটিও কল করতে পারেন Remove সংগ্রহের স্থিতি পরিবর্তন করে। এমএসডিএন.মাইক্রোসফট.ডে- ডি / লাইবারি/… চিয়ার্স দেখুন ।
Andreas Krohn

9
DataRow[] dtr=dtPerson.select("name=Joe");
foreach(var drow in dtr)
{
   drow.delete();
}
dtperson.AcceptChanges();

আমি আশা করি এটা তোমাকে সাহায্য করবে


4
কমান্ডটি পদ্ধতিগুলি নেট নেট drow.Delete();drow.delete();
বিটিডব্লিউ

5

ডেটাবেল থেকে পুরো সারিটি সরাতে , এটি করুন

DataTable dt = new DataTable();  //User DataTable
DataRow[] rows;
rows = dt.Select("UserName = 'KarthiK'");  //'UserName' is ColumnName
foreach (DataRow row in rows)
     dt.Rows.Remove(row);

4

অথবা কেবলমাত্র একটি ডেটাটেবল সারি সংগ্রহকে একটি তালিকায় রূপান্তর করুন :

foreach(DataRow dr in dtPerson.Rows.ToList())
{
    if(dr["name"].ToString()=="Joe")
    dr.Delete();
}

1

সমস্যাটি কোথায়: ফোরচ লুপের ভিতরে সংগ্রহ থেকে আইটেমগুলি মুছে ফেলা নিষিদ্ধ।

সমাধান: হয় তা উইডার লিখেছেন, বা দুটি লুপ ব্যবহার করুন। ডেটা টেবিলের প্রথম পাসে আপনি কেবল সরিয়ে ফেলতে চান সারিগুলির উল্লেখগুলি কেবলমাত্র (একটি অস্থায়ী তালিকায়) সঞ্চয় করে রাখুন। তারপরে আপনার অস্থায়ী তালিকার দ্বিতীয় পাসের মধ্যে আপনি সেই সারিগুলি মুছবেন।


1
<asp:GridView ID="grd_item_list" runat="server" AutoGenerateColumns="false" Width="100%" CssClass="table table-bordered table-hover" OnRowCommand="grd_item_list_RowCommand">
    <Columns>
        <asp:TemplateField HeaderText="No">
            <ItemTemplate>
                <%# Container.DataItemIndex + 1 %>
            </ItemTemplate>
        </asp:TemplateField>            
        <asp:TemplateField HeaderText="Actions">
            <ItemTemplate>                    
                <asp:Button ID="remove_itemIndex" OnClientClick="if(confirm('Are You Sure to delete?')==true){ return true;} else{ return false;}" runat="server" class="btn btn-primary" Text="REMOVE" CommandName="REMOVE_ITEM" CommandArgument='<%# Container.DataItemIndex+1 %>' />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

 **This is the row binding event**

protected void grd_item_list_RowCommand(object sender, GridViewCommandEventArgs e) {

    item_list_bind_structure();

    if (ViewState["item_list"] != null)
        dt = (DataTable)ViewState["item_list"];


    if (e.CommandName == "REMOVE_ITEM") {
        var RowNum = Convert.ToInt32(e.CommandArgument.ToString()) - 1;

        DataRow dr = dt.Rows[RowNum];
        dr.Delete();

    }

    grd_item_list.DataSource = dt;
    grd_item_list.DataBind();
}

1

আমি জানি এটি খুব পুরানো প্রশ্ন এবং কিছু দিন আগে আমারও একই অবস্থা ছিল।

সমস্যা ছিল আমার টেবিলে প্রায়। 10000 সারি, সুতরাং ট্রুপের DataTableসারিগুলি লুপিং খুব ধীর ছিল।

অবশেষে, আমি আরও দ্রুত সমাধান পেয়েছি, যেখানে আমি DataTableকাঙ্ক্ষিত ফলাফল, স্পষ্ট উত্স DataTableএবং mergeঅস্থায়ী DataTableথেকে উত্স থেকে ফলাফলের সাথে উত্সের অনুলিপি তৈরি করি ।

নোট : তার জন্যে অনুসন্ধান Joeমধ্যে DataRowনামক nameআপনি সমস্ত রেকর্ড যার নাম নেই জন্য অনুসন্ধান করতে আছে Joe(অনুসন্ধানের সামান্য বিপরীত পথ)

উদাহরণ রয়েছে ( vb.net):

'Copy all rows into tmpTable whose not contain Joe in name DataRow
Dim tmpTable As DataTable = drPerson.Select("name<>'Joe'").CopyToTable
'Clear source DataTable, in Your case dtPerson
dtPerson.Clear()
'merge tmpTable into dtPerson (rows whose name not contain Joe)
dtPerson.Merge(tmpTable)
tmpTable = Nothing

আমি আশা করি তাই এই সংক্ষিপ্ত সমাধানটি কাউকে সহায়তা করবে।

নেই c#কোড (না এটি সঠিক কারণ আমি অনলাইনে কনভার্টার ব্যবহার :( হয়):

//Copy all rows into tmpTable whose not contain Joe in name DataRow
DataTable tmpTable = drPerson.Select("name<>'Joe'").CopyToTable;
//Clear source DataTable, in Your case dtPerson
dtPerson.Clear();
//merge tmpTable into dtPerson (rows whose name not contain Joe)
dtPerson.Merge(tmpTable);
tmpTable = null;

অবশ্যই, Try/Catchযদি কোনও ফলাফল না পাওয়া যায় তবে আমি ব্যবহার করেছি (উদাহরণস্বরূপ, যদি এটি dtPersonনা থাকে তবে name Joeএটি ব্যতিক্রম ছুঁড়ে ফেলবে), তাই আপনি আপনার টেবিলের সাথে কিছুই করেন না, এটি অপরিবর্তিত থাকে।


0

আমার অ্যাপটিতে আমার একটি ডেটাসেট রয়েছে এবং আমি এটিতে পরিবর্তনগুলি সারি করতে (একটি সারি মুছে ফেলতে) গিয়েছিলাম তবে এটি কেবল ds.tabales["TableName"]পঠনযোগ্য। তারপরে আমি এই সমাধানটি পেয়েছি।

এটি একটি ডাব্লুপিএফ C#অ্যাপ্লিকেশন,

try {
    var results = from row in ds.Tables["TableName"].AsEnumerable() where row.Field<string>("Personalid") == "47" select row;                
    foreach (DataRow row in results) {
        ds.Tables["TableName"].Rows.Remove(row);                 
    }           
}

0

আপনি ডেটা টেবিল থেকে আইডি কলামটি পেতে এবং সরানোর জন্য এটি চেষ্টা করে

if (dt1.Columns.Contains("ID"))
{
    for (int i = dt1.Rows.Count - 1; i >= 0; i--)
    {
        DataRow dr = dt1.Rows[i];

        if (dr["ID"].ToString() != "" && dr["ID"].ToString() != null)
        {
            dr.Delete();
        }
    }

    dt1.Columns.Remove("ID");
}

0

আমি এখানে বিভিন্ন বিট এবং সঠিক উত্তরের টুকরোগুলি দেখতে পাচ্ছি, তবে আমাকে এগুলি একত্রিত করে কয়েকটি জিনিস ব্যাখ্যা করতে দিন।

প্রথমত, AcceptChangesকেবলমাত্র কোনও টেবিলে পুরো লেনদেনকে বৈধ ও প্রতিশ্রুতিবদ্ধ হিসাবে চিহ্নিত করতে ব্যবহার করা উচিত। যার অর্থ যদি আপনি বাঁধার জন্য উদাহরণস্বরূপ, কোনও এসকিউএল সার্ভারের জন্য ডেটা টেবিলটিকে ডেটাসোর্স হিসাবে ব্যবহার করেন তবে AcceptChangesম্যানুয়ালি কল করা গ্যারান্টি দেয় যে পরিবর্তনগুলি কখনই এসকিউএল সার্ভারে সংরক্ষণ হয় না

এই বিষয়টিকে আরও বিভ্রান্তিকর করে তোলে যে বাস্তবে দুটি ক্ষেত্রে ব্যতিক্রম ছুঁড়ে দেওয়া হয়েছে এবং আমাদের উভয়টিকে আটকাতে হবে।

1. একটি আইনিম্যারেবলের কালেকশনটি সংশোধন করা

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

2. একটি মুছে ফেলা এন্ট্রি পড়ার চেষ্টা করা

যেহেতু ডেটা টেবিলগুলি লেনদেনের সংগ্রহ, এন্ট্রিগুলি মোছার জন্য চিহ্নিত করা যেতে পারে তবে এখনও গণনায় প্রদর্শিত হয়। যার অর্থ আপনি যদি কলামটির জন্য মুছে ফেলা প্রবেশের কথা জিজ্ঞাসা করেন "name"তবে এটি একটি ব্যতিক্রম ছুঁড়ে দেবে। যার অর্থ dr.RowState != DataRowState.Deletedকলাম জিজ্ঞাসা করার আগে আমাদের অবশ্যই তা পরীক্ষা করে দেখতে হবে ।

সবগুলোকে একত্রে রাখ

আমরা অগোছালো হয়ে উঠতে পারি এবং ম্যানুয়ালি সেগুলি সবই করতে পারি, বা আমরা ডাটা টেবিলটিকে আমাদের জন্য সমস্ত কাজ করতে দিতে পারি এবং বিবৃতিটি দেখতে এবং আরও কিছু করে এসকিউএল কলের মতো করতে পারি:

string name = "Joe";
foreach(DataRow dr in dtPerson.Select($"name='{name}'"))
    dr.Delete();

ডেটা টেবলের ফাংশনটিতে কল Selectকরে, আমাদের ক্যোয়ারী স্বয়ংক্রিয়ভাবে ডেটাটেবেলে মুছে ফেলা প্রবেশগুলি এড়িয়ে চলে। এবং যেহেতু Selectফাংশনটি ম্যাচের একটি অ্যারে দেয়, তাই আমরা যে সংগ্রহটি গণনা করছি তা কল করার সময় পরিবর্তন করা হয় না dr.Delete()। কোডটি শোরগোল না করে পরিবর্তনশীল নির্বাচনের অনুমতি দেওয়ার জন্য আমি স্ট্রিং ইন্টারপোলেশন সহ সিলেক্ট এক্সপ্রেশনটিও মশগুল করেছি।


0

সহজ উপায় এটি বোতামে ব্যবহার করুন:

 var table = $('#example1').DataTable();
 table.row($(`#yesmediasec-${id}`).closest('tr')).remove( ).draw();

উদাহরণ 1 = আইডি টেবিল। হ্যাঁমিডেসেক = সারির বোতামটির আইডি

এটি ব্যবহার করুন এবং প্রতিটি জিনিস ঠিক হয়ে যাবে

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