Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the compiler think this is an Object instead of a DataRow?

I'm using a LINQ query to translate data inside a DataTable object to be a simple IEnumerable of a custom POCO object.

My LINQ query is:

    Dim dtMessages As DataTable

    '...dtMessages is instantiated ByRef in a helper data access routine... '

    Dim qry = From dr As DataRow In dtMessages.Rows
              Select New OutboxMsg With {
                  .ComputerID = dr(dcComputerID),
                  .MessageData = dr(dcMessageData),
                  .OutBoxID = dr(dcOutBoxID),
                  .OutBoxReceivedID = dr(dcOutBoxReceivedID),
                  .TrxDate = dr(dcTrxDate)
              }

However, the compiler is throwing a warning message under dr As DataRow with the message:

Option Strict On disallows implicit conversions from 'Object' to 'System.Data.DataRow'.

Why am I getting this error and what do I need to do to fix it? I would have thought that dtMessages.Rows returned a collection of type DataRow. Is this not correct?

like image 573
Ben McCormack Avatar asked Aug 02 '10 14:08

Ben McCormack


3 Answers

Lok at DataTable.Rows - it's a DataRowCollection which only implements IEnumerable, not IEnumerable(Of DataRow).

Fortunately, there's an extension method in DataTableExtensions which lets you call AsEnumerable() instead of Rows; AsEnumerable returns an IEnumerable(Of DataRow):

Dim qry = From dr As DataRow In dtMessages.AsEnumerable()
          ...

(I prefer this over using dt.Rows.Cast(Of DataRow), as it gives less of an impression of something which might fail. It's more tailored to DataTable. Both will work though.)

like image 133
Jon Skeet Avatar answered Nov 11 '22 12:11

Jon Skeet


The type System.DataTable predates generics in .Net and hence returns a plain old IEnumerable instead of an IEnumerable(Of DataRow) even though under the hood they are instances of DataRow. Hence the type of dr in the above query is Object and not DataRow.

You can work around this by using the Cast extension method to make the type of the collection explicit

From dr As DataRow in dtMessages.Rows.Cast(Of DataRow)
like image 43
JaredPar Avatar answered Nov 11 '22 12:11

JaredPar


The DataTable.Rows property returns a collection of DataRow, however that collection doesn't implement IEnumerable<DataRow> but IEnumerable, which works as IEnumerable<Object>.

You can explicitly cast the collection items to DataRow using dtMessages.Rows.Cast<DataRow>().

like image 34
Guffa Avatar answered Nov 11 '22 10:11

Guffa