Repository navigation
Description
API Proposal
namespace Microsoft.ML
{
public static class DatabaseLoaderCatalog
{
public static IDataView LoadFromDatabase(
this DataOperationsCatalog catalog,
DbProviderFactory providerFactory,
string connectionString,
string commandText,
params DatabaseLoader.Column[] columns);
public static IDataView LoadFromDatabase(
this DataOperationsCatalog catalog,
DbProviderFactory providerFactory,
string connectionString,
string commandText,
DatabaseLoader.Options options);
public static IDataView LoadFromDatabase<TInput>(
this DataOperationsCatalog catalog,
DbProviderFactory providerFactory,
string connectionString,
string commandText);
public static IDataView LoadFromDatabase(
this DataOperationsCatalog catalog,
DatabaseSource source,
params DatabaseLoader.Column[] columns);
public static IDataView LoadFromDatabase(
this DataOperationsCatalog catalog,
DatabaseSource source,
DatabaseLoader.Options options);
public static IDataView LoadFromDatabase<TInput>(
this DataOperationsCatalog catalog,
DatabaseSource source);
}
}Example usage
using System.Data; // DbType
using Microsoft.Data.SqlClient; // SqlClientFactory; any ADO.NET provider works
using Microsoft.ML;
using Microsoft.ML.Data; // DatabaseLoader, DatabaseSource
var mlContext = new MLContext();
string connectionString = "<your connection string>";
string commandText = "SELECT CAST(Size as REAL) as Size, CAST(NumBed as REAL) as NumBed, Price FROM House";
// Today (the Learn docs sample): three steps
DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader<HouseData>();
DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance, connectionString, commandText);
IDataView data = loader.Load(dbSource);
// Proposed: one call. Choose one way to give the schema (<TInput>, columns or options)
// and one way to give the source (factory + connection string + command text, or DatabaseSource).
// Explicit schema, for when there is no class (e.g. columns chosen at runtime).
// Result columns 0-1 (Size, NumBed) become one Features vector, and column 2 (Price) becomes Label.
var columns = new[]
{
new DatabaseLoader.Column("Features", DbType.Single, 0, 1),
new DatabaseLoader.Column("Label", DbType.Single, 2),
};
var options = new DatabaseLoader.Options { Columns = columns };
// Factory, connection string and command text
data = mlContext.Data.LoadFromDatabase<HouseData>(SqlClientFactory.Instance, connectionString, commandText);
data = mlContext.Data.LoadFromDatabase(SqlClientFactory.Instance, connectionString, commandText, columns);
data = mlContext.Data.LoadFromDatabase(SqlClientFactory.Instance, connectionString, commandText, options);
// DatabaseSource, e.g. for a longer command timeout (the default is 30 s)
var source = new DatabaseSource(SqlClientFactory.Instance, connectionString, commandText,
commandTimeoutInSeconds: 300);
data = mlContext.Data.LoadFromDatabase<HouseData>(source);
data = mlContext.Data.LoadFromDatabase(source, columns);
data = mlContext.Data.LoadFromDatabase(source, options);
// columns is params, so you can also pass the Column values inline:
data = mlContext.Data.LoadFromDatabase(SqlClientFactory.Instance, connectionString, commandText,
new DatabaseLoader.Column("Features", DbType.Single, 0, 1),
new DatabaseLoader.Column("Label", DbType.Single, 2));
// None of these calls query the database. The query runs when the view is enumerated (Preview, Fit, CreateEnumerable).
// Same class as the Learn docs sample. Members map to result columns by name, so no attributes are needed.
public class HouseData
{
public float Size { get; set; }
public float NumBed { get; set; }
public float Price { get; set; }
}As mentioned by Diego, these additions would help by simplifying the API usage for users even further and it should be pretty easy to implement for us: 👍
@divega commented: dotnet/machinelearning-samples#617 (review)
@CESARDELATORRE, I did a deferred review. The experience seems pretty good.
1:
And I agree with you that it could be even better with some sugar method that loads directly from the arguments of DatabaseSource.
2:
I can also see other possible shortcuts of similar nature. For example, although DbProviderFactory is the all encompassing root concept if you need everything from an ADO.NET provider, a DbConnection can give you everything but DbConnectionStringBuilder, and it is a much more familiar abstraction for most users than the DbProviderFactory. So, unless you need to manipulate connection strings in a provider agnostic way (not commonly an useful thing to do), you could make the sugar Load method generic on the provider's DbConnection type.
All in all, I would would love to meet with you and the devs and walk trough the product code and API. It is likely that more things like this will come up.
Activity
Pomoinytskyi commentedon Dec 27, 2019
Hi @divega and @CESARDELATORRE
I am interested in this task. Could you please explain what sugar methods you want to have in more details?
You wrote:
What providers type do you mean under
if I am correctly understand you, it is not the DbProviderFactory.
I can propose such methods:
public static IDataView Load<TData>(this DbConnection connection, string connectionString, string query, IHostEnvironment host)or
public static IDataView Load<TData>(this DatabaseSource source, string connectionString, string query, IHostEnvironment host)Thanks.
avishekhraj9 commentedon Jun 17, 2026
Hi @CESARDELATORRE @eerhardt — I'd like to take this one if it's still open for contribution.
Building on @Pomoinytskyi's suggestion above, my plan is to add convenience "sugar" overloads so users can load directly from a familiar
DbConnectionwithout setting up aDbProviderFactoryfor the common case, e.g.:making the method generic over the provider's
DbConnectiontype. I'd include unit tests and XML doc comments, and keep the existingDbProviderFactory-based API intact for the provider-agnostic scenarios.Does that direction look right? If so, I'll open a PR referencing this issue. Thanks! @avishekhraj9
Add LoadFromDatabase convenience methods (dotnet#4182)
Use a fast in-memory SQLite load test for LoadFromDatabase (dotnet#4182)
8 remaining items
adestr commentedon Sep 30, 2026
@rosebyte thanks, and that makes total sense to me. I was a bit surprised it was marked as "good first issue" considering the API exposure. Just to clarify, are you saying "leave it to the ML team" or "feel free to submit an API proposal"? I'm assuming the former, but thought it was worth checking.
svick commentedon Sep 30, 2026
@adestr Feel free to submit an API proposal in a comment here. Then leave it to us to check it and get it through the rest of the API review process.
Take a look for example at dotnet/runtime#27421, to see how an API proposal should look like.
rosebyte commentedon Oct 1, 2026
I've extracted the API from the PR (only moved
Loadmethods to extensions), please let me know if there is anything missing.Allow loading directly from a provider factory or an existing
DbConnection, without constructing aDatabaseSource.Precedent and differences
DataLoaderExtensions.Load(this IDataLoader<IMultiStreamSource> loader, params string[] path)already wraps source construction asloader.Load(new MultiFileSource(path)). These overloads follow the same pattern withDatabaseSource. Unlike instance methods, interface extensions also work with composite loaders returned byloader.Append(transformer).DatabaseSourcealready has provider-factory constructors with and without an explicit timeout. The connection constructors mirror that pair. The newLoadoverloads use the existing 30-second default; custom timeouts still require a source object.ProviderFactoryandConnectionStringproperties returnnull;Connectionreturnsnullfor factory-backed sources. Existing factory-created sources are unchanged, but consumers inspecting arbitrary sources must handle the new mode.adestr commentedon Oct 1, 2026
Thank you. Given that the spirit of the original request was "make it easier to load from a database", I was also considering whether some extension to
DatabaseLoaderCatalogwould be useful, similar to theLoadFromFileextensions inTextLoaderSaverCatalog. Given the range of possible method signatures (below), I wasn't sure if anAction<DatabaseLoader.Options>or similar would be easier, but wanted to do some research to figure out how that would work alongside existing command line parsing ofDatabaseLoader.Columnarguments.Considering I haven't seen use of
Action<T>for configuration, I think it would be better to suggest these extension methods.rosebyte commentedon Oct 13, 2026
@adestr, the latest proposal looks good to me. Thanks for putting it together. We’ll now take it through the API review process.
bartonjs commentedon Oct 16, 2026
@rosebyte Please update the top post to contain the API proposal. We're not good at "scroll down to the proposal, please"
bartonjs commentedon Nov 3, 2026
Video
Looks good as proposed
rosebyte commentedon Nov 4, 2026
@adestr, we have the API approved, are you still happy to propose a PR for the new API? Or you prefer us to take care of it?
adestr commentedon Nov 4, 2026
@rosebyte I will get a PR ready shortly.