System.Data.Common.DataAdapter: RowUpdated & RowUp

2019-07-23 13:16发布

问题:

I'm currently working on a program that allows for connections to multiple provider specific databases, so obviously I'm using the non-provider-specific classes (in System.Data.Common) to work with these various connections once the connection or data adapter has been instantiated through the use of the provider's implementation.

However, I wanted to make use of the RowUpdated and RowUpdating events that are supposedly a part of the DataAdapter base class according to MSDN (http://msdn.microsoft.com/en-us/library/6d1wk41s.aspx). But obviously this is not the case, because those events are only implemented through the provider-specific implementations of DbDataAdapter (like SqlDataAdapter, OleDbDataAdapter, etc.).

My main goal is to be able to handle those events through the use of the generic DbDataAdapter class, and it will be a big pain to have to cast things back to the derived classes of the provider-specific implementations for the data adapter.

Any slick ideas of doing this?

回答1:

I did a lot of searching online, and really didn't find anything concrete besides just re-casting instances back to the derived classes to access those events.

So, with the use of Extension Methods, I added two new methods to the DbDataAdapter abstract class that will allow the adding of event handlers for those two specific events, and here is my implementation (edited 4/23/2013 for handling of instance or static handler methods):

using System;
using System.Data.Common;
using System.Reflection;

namespace Extensions
{
    /// <summary>
    /// Delegate event handler used with the <c>DbDataAdapter.RowUpdated</c> event.
    /// </summary>
    public delegate void RowUpdatedEventHandler(object sender, RowUpdatedEventArgs e);

    /// <summary>
    /// Delegate event handler used with the <c>DbDataAdapter.RowUpdating</c> event.
    /// </summary>
    public delegate void RowUpdatingEventHandler(object sender, RowUpdatingEventArgs e);

    public static class DbDataAdapterExtension
    {
        private static EventInfo GetEvent(string eventName, Type type)
        {
            return type.GetEvent(eventName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
        }

        /// <summary>
        /// Registers a <c>RowUpdatedEventHandler</c> with this instance's <c>RowUpdated</c> event.
        /// </summary>
        /// <param name="handler">The event handler to register for the event.</param>
        /// <returns><c>true</c> if the event handler was successfully registered, otherwise <c>false</c>.</returns>
        public static bool AddRowUpdatedHandler(this DbDataAdapter adapter, RowUpdatedEventHandler handler)
        {
            EventInfo updEvent = GetEvent("RowUpdated", adapter.GetType());

            if (updEvent != null)
            {
                try
                {
                    if (handler.Method.IsStatic)
                    {
                        updEvent.AddEventHandler(adapter, Delegate.CreateDelegate(updEvent.EventHandlerType, handler.Method));
                    }
                    else
                    {
                        updEvent.AddEventHandler(adapter, Delegate.CreateDelegate(updEvent.EventHandlerType, handler.Target, handler.Method));
                    }

                    return true;
                }
                catch { }
            }

            return false;
        }

        /// <summary>
        /// Registers a <c>RowUpdatingEventHandler</c> with this instance's <c>RowUpdating</c> event.
        /// </summary>
        /// <param name="handler">The event handler to register for the event.</param>
        /// <returns><c>true</c> if the event handler was successfully registered, otherwise <c>false</c>.</returns>
        public static bool AddRowUpdatingHandler(this DbDataAdapter adapter, RowUpdatingEventHandler handler)
        {
            EventInfo updEvent = GetEvent("RowUpdating", adapter.GetType());

            if (updEvent != null)
            {
                try
                {
                    if (handler.Method.IsStatic)
                    {
                        updEvent.AddEventHandler(adapter, Delegate.CreateDelegate(updEvent.EventHandlerType, handler.Method));
                    }
                    else
                    {
                        updEvent.AddEventHandler(adapter, Delegate.CreateDelegate(updEvent.EventHandlerType, handler.Target, handler.Method));
                    }

                    return true;
                }
                catch { }
            }

            return false;
        }
    }
}

I'm using the base RowUpdatedEventArgs & RowUpdatingEventArgs for the event arguments that get returned to the delegate, so if you need provider-specific members that are only available through the provider defined classes that are derived from the above two base event args classes, then they will need to be cast to those classes. Otherwise, it works fine, and now I have provider-independent event handlers available from the DbDataAdapter class (which is how Microsoft should have implemented them to begin with).

Cheers!



回答2:

Thank You - very useful!

Perhaps someone needs this in Visual Basic

Call it like this for example:

Imports YourProject.DbDataAdapterExtension

. . .

Dim HandleOnRowUpd As RowUpdatedEventHandler = AddressOf OnRowUpdated

Dim TrueFalse As Boolean = YourDataAdapter.AddRowUpdatedHandler(HandleOnRowUpd)

Imports System.Data.Common
Imports System.Reflection
Imports System.Runtime.CompilerServices

' Namespace Extensions

''' <summary>
''' Delegate event handler used with the <c>DbDataAdapter.RowUpdated</c> event.
''' </summary>
''' 
Public Delegate Sub RowUpdatedEventHandler(sender As Object, e As RowUpdatedEventArgs)

''' <summary>
''' Delegate event handler used with the <c>DbDataAdapter.RowUpdating</c> event.
''' </summary>
''' 
Public Delegate Sub RowUpdatingEventHandler(sender As Object, e As RowUpdatingEventArgs)

Public Module DbDataAdapterExtension

    Sub New()
    End Sub

    Private Function GetEvent(eventName As String, type As Type) As EventInfo
        Return type.GetEvent(eventName, BindingFlags.[Public] Or BindingFlags.Instance Or BindingFlags.DeclaredOnly)
    End Function

    ''' <summary>
    ''' Registers a <c>RowUpdatedEventHandler</c> with this instance's <c>RowUpdated</c> event.
    ''' </summary>
    ''' <param name="handler">The event handler to register for the event.</param>
    ''' <returns><c>true</c> if the event handler was successfully registered, otherwise <c>false</c>.</returns>
    ''' 
    <Extension> Public Function AddRowUpdatedHandler(adapter As DbDataAdapter, handler As RowUpdatedEventHandler) As Boolean

        Dim updEvent As EventInfo = GetEvent("RowUpdated", adapter.[GetType]())

        If updEvent IsNot Nothing Then
            Try
                If handler.Method.IsStatic Then
                    updEvent.AddEventHandler(adapter, [Delegate].CreateDelegate(updEvent.EventHandlerType, handler.Method))
                Else
                    updEvent.AddEventHandler(adapter, [Delegate].CreateDelegate(updEvent.EventHandlerType, handler.Target, handler.Method))
                End If

                Return True
            Catch
            End Try
        End If

        Return False
    End Function

    ''' <summary>
    ''' Registers a <c>RowUpdatingEventHandler</c> with this instance's <c>RowUpdating</c> event.
    ''' </summary>
    ''' <param name="handler">The event handler to register for the event.</param>
    ''' <returns><c>true</c> if the event handler was successfully registered, otherwise <c>false</c>.</returns>
    ''' 
    <Extension> Public Function AddRowUpdatingHandler(adapter As DbDataAdapter, handler As RowUpdatingEventHandler) As Boolean

        Dim updEvent As EventInfo = GetEvent("RowUpdating", adapter.[GetType]())

        If updEvent IsNot Nothing Then
            Try
                If handler.Method.IsStatic Then
                    updEvent.AddEventHandler(adapter, [Delegate].CreateDelegate(updEvent.EventHandlerType, handler.Method))
                Else
                    updEvent.AddEventHandler(adapter, [Delegate].CreateDelegate(updEvent.EventHandlerType, handler.Target, handler.Method))
                End If

                Return True
            Catch
            End Try
        End If

        Return False
    End Function
End Module

' End Namespace