1

I've a piece of code that fills a database table from a DataTable using a DbDataAdapter.

The DbDataAdapter is created via DbProviderFactory.CreateDataAdapter method, where DbProviderFactory is provided by Devart dotConnect.
We use Devart's drivers for Oracle, SqlServer and Postgres.

Since I have nearly 100k rows in my DataTable, I need to bind to the RowUpdated event (to update a progress bar) which unfortunately is not defined on a common interface, despite it is available in all the mentioned database drivers.

Therefore I bind it via reflection with this code:

Dim eventInfo As System.Reflection.EventInfo = adapter.GetType().GetEvent("RowUpdated")
eventInfo.AddEventHandler(adapter, [Delegate].CreateDelegate(eventInfo.EventHandlerType,
                          (Sub(s As Object, e As EventArgs) UpdateProgress(s, e)).Method))

This perfectly works if compiled with VS2013, but fails at runtime if compiled on Roslyn (VS2015), with this exception:

Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type

Any help on this?

Neither using Devart.Data.PostgreSql.PgSqlRowUpdatedEventHandler (I'm currently on Postgres) as the type of e works.

djv
  • 15,168
  • 7
  • 48
  • 72
Teejay
  • 7,210
  • 10
  • 45
  • 76
  • Does it work with `e As Devart.Data.PostgreSql.PgSqlRowUpdatedEventArgs` in the handler? – djv Apr 03 '17 at 18:12
  • @djv ouch! I used the event handler, instead of event args! I'll try tomorrow! – Teejay Apr 03 '17 at 18:15
  • @djv I'll try the correct one tomorrow, anyway I'd like to avoid to be so specific because this way I would have to test for the DbType and then use the specific event. – Teejay Apr 03 '17 at 18:18
  • Right, if the same handler must work for Oracle, SqlServer and Postgres. It would be interesting to see if that works, then it might be a question for Devart support. – djv Apr 03 '17 at 18:20
  • @djv I'd want to understand what changed on Roslyn that make it doesn't work... – Teejay Apr 03 '17 at 18:22
  • Is there a reason why you need to use Reflection? What about `AddHandler adapter.RowUpdated, Sub(s As Object, e As EventArgs) UpdateProgress(s, e)`? – djv Apr 03 '17 at 19:21
  • As I wrote in the question, `adapter` has no `RowUpdated` event because it is not of a specific class, the event is defined on each specific adapter (i.e. OracleDataAdapter, PgSqlDataAdapter etc). I can for sure test for the correct DB type at runtime and then perform a `select case` to cast `adapter` to che correct specific type, but I'd like to avoid this "so specific" approach. – Teejay Apr 03 '17 at 19:30
  • @djv Neither using `PgSqlRowUpdatedEventArgs` works. But if I cast the adapter to the specific type, it works with a simple `AddHandler` statement, even if the type of `e` is not specific. – Teejay Apr 04 '17 at 08:56
  • See similar question: http://stackoverflow.com/questions/15777483/system-data-common-dataadapter-rowupdated-rowupdating-events-not-present. If that doesn't help, I still think Devart support is your best bet. Seems pretty standard to want to generically handle all table updates. Good luck! – djv Apr 04 '17 at 15:21
  • @djv Thanks, I'll give it a try. The answer is from 2013 so it could not work as well in Roslyn, but it's worth to try. – Teejay Apr 04 '17 at 20:11

1 Answers1

0

Starting from this answer posted in a comment by @djv, I finally get to the culprit.

It seems that, with Roslyn (VS2015), you need to explicitly declare the Delegate prior to binding the event handler.

For example, in my case, I need to write:

Public Delegate Sub RowUpdatedEventHandler(sender As Object, e As RowUpdatedEventArgs)

And then:

Dim eventInfo As System.Reflection.EventInfo = adpt.GetType().GetEvent("RowUpdated")
eventInfo.AddEventHandler(adpt, [Delegate].CreateDelegate(eventInfo.EventHandlerType,
                          DirectCast(AddressOf UpdateProgress, RowUpdatedEventHandler).Method))

Also it seems it has some issues with lamdas. For example, this DOES NOT WORK:

Dim eventInfo As System.Reflection.EventInfo = adpt.GetType().GetEvent("RowUpdated")
eventInfo.AddEventHandler(adpt, [Delegate].CreateDelegate(eventInfo.EventHandlerType,
                          DirectCast((Sub(s As Object, e As RowUpdatedEventArgs) UpdateProgress(s, e)), RowUpdatedEventHandler).Method))

(with or without DirectCast on the lambda expression)

Community
  • 1
  • 1
Teejay
  • 7,210
  • 10
  • 45
  • 76