C# 如何向表适配器中的RowUpdate事件添加事件处理程序

C# 如何向表适配器中的RowUpdate事件添加事件处理程序,c#,ado.net,C#,Ado.net,我有一个tableadapter,我想在触发RowUpdate事件时执行一些操作。我不知道把代码放在哪里,以便将处理程序添加到事件中 public partial class MyTableAdapter { void OnRowUpdated(object sender, System.Data.Odbc.OdbcRowUpdatedEventArgs e) { } } 创建TableAdapter时,如何让下面的代码运行 Adapter.RowUpdated +=

我有一个tableadapter,我想在触发RowUpdate事件时执行一些操作。我不知道把代码放在哪里,以便将处理程序添加到事件中

public partial class MyTableAdapter
{
  void OnRowUpdated(object sender, System.Data.Odbc.OdbcRowUpdatedEventArgs e)
  {
  }
}
创建TableAdapter时,如何让下面的代码运行

Adapter.RowUpdated += 
                   new System.Data.Odbc.OdbcRowUpdatedEventHandler(OnRowUpdated);
编辑:显然,下面建议的步骤没有一个有用。我把这个答案保留在这里纯粹是为了让其他试图回答这个问题的人不会提出同样的建议

是否在设计器中创建TableAdapter?如果是这样,您是否可以单击属性页的事件部分,并在RowUpdated条目中键入OnRowUpdated

如果要在代码中显式创建适配器,只需自己添加调用即可

或者,您的分部类是否具有正在调用的构造函数?同样,如果是这样,您可以在那里添加呼叫


编辑:好的,假设这是在一个特定的页面或表单中使用的-你能在该页面/表单的InitializeComponent方法之后添加它吗?

如果你看这个视频,你会看到,您只需双击dataset designer中的某个内容,事件就会为您生成并连接起来……但这只适用于VB程序员:sux自从我上次使用这个东西已经有一段时间了,但是如果我没记错的话,您应该能够在分部类中重写EndInit并添加init代码,就像在那里添加事件处理程序一样…

在C类中重写EndInit并从那里启动事件处理程序

    public override void EndInit()
    {
        base.EndInit();
        Adapter.RowUpdated += 
                   new System.Data.Odbc.OdbcRowUpdatedEventHandler(OnRowUpdated);

    }

    void OnRowUpdated(object sender, System.Data.Odbc.OdbcRowUpdatedEventArgs e)
    {

    }

希望这有助于…………

我分两个阶段解决了这个问题

// Assumes that connection is a valid SqlConnection object.

SqlDataAdapter custAdapter = new SqlDataAdapter(
  "SELECT CustomerID, CompanyName FROM Customers", connection);

// Add handlers.

custAdapter.RowUpdating += new SqlRowUpdatingEventHandler(OnRowUpdating);
custAdapter.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated);

// Set DataAdapter command properties, fill DataSet, modify DataSet.


custAdapter.Update(custDS, "Customers");

// Remove handlers.

custAdapter.RowUpdating -= new SqlRowUpdatingEventHandler(OnRowUpdating);
custAdapter.RowUpdated -= new SqlRowUpdatedEventHandler(OnRowUpdated);

protected static void OnRowUpdating(
  object sender, SqlRowUpdatingEventArgs args)
{
  if (args.StatementType == StatementType.Delete)
  {
    System.IO.TextWriter tw = System.IO.File.AppendText("Deletes.log");
    tw.WriteLine(
      "{0}: Customer {1} Deleted.", DateTime.Now, 
       args.Row["CustomerID", DataRowVersion.Original]);
    tw.Close();
  }
}

protected static void OnRowUpdated(
  object sender, SqlRowUpdatedEventArgs args)
{
  if (args.Status == UpdateStatus.ErrorsOccurred)
  {
    args.Row.RowError = args.Errors.Message;

    args.Status = UpdateStatus.SkipCurrentRow;
  }
}
a。添加分部类和扩展表适配器

b。在使用此适配器之前,首先调用一个方法,例如在创建其实例之后,在主窗体中调用该方法

下面的代码是为了解决SQL CE的特殊问题,以便能够更新表上的ID。但是,您可以使用扩展方法包装RowUpdated事件,并将其公开给其他类,如MyRowUpdated

分机

public partial class ScannedItemsTableAdapter
{
    public void InitEvents()
    {
        this._adapter.RowUpdated += _adapter_RowUpdated;
    }

    void _adapter_RowUpdated(object sender, SqlCeRowUpdatedEventArgs e)
    {
        if (e.Status == UpdateStatus.Continue && 
            e.StatementType == StatementType.Insert)
        {
            var pk = e.Row.Table.PrimaryKey;
            pk[0].ReadOnly = false;

            SqlCeCommand cmd = new SqlCeCommand("SELECT @@IDENTITY", 
               e.Command.Connection, e.Command.Transaction);

            object id = (decimal)cmd.ExecuteScalar();

            e.Row[pk[0]] = Convert.ToInt32(id);
            e.Row.AcceptChanges();
        }
    }
}
主要形式的调用:

        tableAdapter = new ScannedItemsTableAdapter();
        tableAdapter.Fill(ds.ScannedItems);
        tableAdapter.InitEvents();

我有一个可能的选择

虽然人们可以订阅tableadapter部分类中的tableadapter底层适配器,但我发现如果不记得调用自己的初始化,就无法轻松初始化它

但是,我发现我可以使用下面的TableAdapter从代码中直接订阅tableadapters.adapter.RowUpdate事件

AddHandler Me.TA_Case_Transactions.Adapter.RowUpdated, AddressOf Transaction_Row_Written

  Private Sub Transaction_Row_Written(p_Sender As Object, p_E As SqlRowUpdatedEventArgs)
        beep
    End Sub
嘟嘟声很响,所以我可以添加一个断点进行测试


因为无论如何我都必须订阅活动,我认为这更直观,不需要任何记忆,这里有一个简单的方法,使用设计器。右键单击数据集.xsd文件并选择查看代码。就像表单一样,它不会打开设计器代码。它将打开你的代码。这是您的代码:

namespace TimeTrack.TimeTrackDataSetTableAdapters
{
    public partial class TimeSlipsTableAdapter
    {
        public void CustomSetup()
        {
            Adapter.RowUpdated += Adapter_RowUpdated;
        }

        private void Adapter_RowUpdated(object sender, OleDbRowUpdatedEventArgs e)
        {
            // whatever you want to do when RowUpdated fires
        }
    }
}
在你的状态下,别忘了

    public TimeEntry()
    {
        InitializeComponent();
        timeSlipsTableAdapter.CustomSetup();

如果您有机会在适配器创建之后将其放置,如果你有一个InitializeComponent方法在容器类的构造函数中为你进行初始化,我会把它放在那里,把代码放在InitializeComponent调用之后。我对这个问题给予了奖励,因为这是一个从.net 1.1时代起我就经常遇到的问题,我觉得一定有更好的解决方案这比在我实例化表适配器后对其进行黑客攻击要好得多。回答中提供的解决方案在实用性上很好,技术上也很可靠。我正在使用设计器创建一个带有数据表和表适配器的类型化数据集。属性页中没有我可以看到的事件部分。因为设计器已经创建了一个构造函数,所以我不能在分部类中添加到它。@Simon:我指的是您正在使用适配器的设计器,即表单/无论您在哪里包含它。不是数据集设计器。我可以将OnRowUpdated处理程序公开,并在以下表单上使用此代码:MyTableAdapter myAdapter=new MyTableAdapter;myAdapter.Adapter.RowUpdated+=new System.Data.Odbc.OdbcRowUpdatedEventHandlermyAdapter.OnRowUpdated;但是,我更愿意在适配器的分部类中执行此操作,这样数据集的用户就不必在每次创建适配器实例时都记得添加此代码。Jon,表单上也没有“事件”窗格。好吧,看起来这个答案不是很有用。。。将编辑这样说,但将其保留为我们尝试过的事情列表:更具体地说,@5:00 minute Beth双击数据表并获取xxRowEventAnswers如果附有一些解释,则会更好,TableAdapter类不允许您重写EndInit,因为找不到合适的方法来重写它。DataTable分部类确实允许您重写EndInit,但是我看不出如何从DataTable访问相关的TableAdapter。这就是我解决问题的方法,但是我正在寻找一种在table adapte中连接事件的方法
创建表适配器时使用r类。谢谢。我也是这样结束的。对于将来的读者,请确保在初始化适配器对象之后而不是在窗体的构造函数中调用InitEvents。