Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News System.Data in .NET Core 3.0

System.Data in .NET Core 3.0

Leia em Português

This item in japanese

While it doesn't get a lot of attention, System.Data is crucial for any sort of relational database access in .NET. Also known as ADO.NET in honor of its predecessor, ActiveX Data Objects, System.Data provides a generic framework upon which .NET database drivers can be built. This framework provides for certain conventions database drivers are expected to adhere to.

Connections, commands, and data readers are all based on a dual inheritance scheme. Each inherits some basic functionality from DbConnection, DbCommand, and DbDataReader respectively. They also implement the abstract interfaces IDbConnection, IDbCommand, and IDbDataReader, which allows for mocking scenarios and non-traditional data sources. This dual inheritance scheme is also used for all of the base classes described below.

While connection strings are normally thought of as strings, facilities exist for representing them as objects that inherit from DbConnectionStringBuilder. This handles database specific parsing of connection strings and gives the developer a better idea of what settings are available for a particular database.

System.Data predates ORMs for .NET, but it does offer a generic way to generate SQL via implementations of the DbDataAdapter and DbCommandBuilder classes. This was used both directly and in conjunction with normal and typed DataSets.

If you are looking for a real-world example of the abstract factory pattern, look at the DbProviderFactory. Subclasses of this provide connections, commands, command parameters, command builders, and data adapters. Essentially everything you need for data access without the need for database specific logic.

The Problem with Interfaces

As mentioned above, System.Data relies on dual inheritance. This can be a problem when adding new methods. For example, asynchronous operations were added to DbCommand in .NET 4.5. However, they could not be added to the matching IDbCommand interface because that would be a breaking change. Which in turn means you cannot use both asynchronous operations and the easily mocked abstract interface at the same time.

Microsoft could have done a one-time reset of the abstract interfaces in .NET Core 1.0 so they match the abstract classes (Java has done this in the past with JDBC interfaces). However, that would make sharing code with .NET Framework difficult.

If default interface methods make it into C# 8, then in theory they could be used to realign the interfaces in a backwards compatible manner. But again, that wouldn't be compatible with .NET Framework since default interface methods is a .NET Core only feature. Nor would it work with older compilers and other .NET languages.

String Overloads for DbDataReader.Get*() #31595

Our first .NET Core 3.0 feature is the ability to pass a column name to the DbDataReader.GetXXX methods. A long-time complaint about this interface is you cannot refence columns by name. Which means instead you need to use this pattern:


An obvious (and to some, long overdue) simplification is to offer a string overload.


This has already been done in Oracle's Connector/NET and MySqlConnector.

For performance reasons this new method will not be marked as virtual, allowing the JIT compiler to easily inline it. And for the reasons mentioned above, the new set of methods will not be added to IDbDataReader.

XmlDataDocument #33442

If you know the history of XmlDataDocument, this may seem like an odd pick. It has been marked as obsolete with the warning 'XmlDataDocument class will be removed in a future release' since .NET 4.0 was released in 2010.

The reason it is being picked up now is some WinForms and WPF applications use it. The bug report says, "This has 1-7% of usage in various categories from Apiport."


One feature that won't be made available in .NET Core 3 is DataTableExtensions class. While it appears to be fairly simple with only six extension methods, the AsDataView cannot be built without modifications to System.Data itself. The reasoning is fairly complex, having to do with internal methods, type forwarding, and the challenges posed by .NET Standard.

If you are interested, the relevant conversations are Port DatasetExtensions to .NET Core #19771, Port DataTable.AsDataView extension methods #27610, and Exposing internal virtuals involving searching a key in DataView #31764.

Rate this Article