diff --git a/src/Microsoft.ML.Data/DataLoadSave/Database/DatabaseLoaderCatalog.cs b/src/Microsoft.ML.Data/DataLoadSave/Database/DatabaseLoaderCatalog.cs
index 675f3f39ab..a3bcad6e2e 100644
--- a/src/Microsoft.ML.Data/DataLoadSave/Database/DatabaseLoaderCatalog.cs
+++ b/src/Microsoft.ML.Data/DataLoadSave/Database/DatabaseLoaderCatalog.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Data.Common;
using Microsoft.ML.Data;
namespace Microsoft.ML
@@ -38,5 +39,52 @@ public static DatabaseLoader CreateDatabaseLoader(this DataOperationsCatalog cat
/// The catalog.
public static DatabaseLoader CreateDatabaseLoader(this DataOperationsCatalog catalog)
=> DatabaseLoader.CreateDatabaseLoader(CatalogUtils.GetEnvironment(catalog));
+
+ ///
+ /// Load an from a database using a .
+ /// Note that 's are lazy, so no actual loading happens here, just schema validation.
+ ///
+ /// Defines the schema of the data to be loaded. Use public fields or properties
+ /// decorated with (and possibly other attributes) to specify the column
+ /// names and their data types in the schema of the loaded data.
+ /// The catalog.
+ /// The containing the connection and command information.
+ /// The data view.
+ public static IDataView LoadFromDatabase(this DataOperationsCatalog catalog,
+ DatabaseSource source)
+ => catalog.CreateDatabaseLoader().Load(source);
+
+ ///
+ /// Load an from a database using a .
+ /// Note that 's are lazy, so no actual loading happens here, just schema validation.
+ ///
+ /// Defines the schema of the data to be loaded. Use public fields or properties
+ /// decorated with (and possibly other attributes) to specify the column
+ /// names and their data types in the schema of the loaded data.
+ /// The catalog.
+ /// The factory used to create the .
+ /// The string used to open the connection.
+ /// The text command to run against the data source.
+ /// The data view.
+ public static IDataView LoadFromDatabase(this DataOperationsCatalog catalog,
+ DbProviderFactory providerFactory, string connectionString, string commandText)
+ => catalog.LoadFromDatabase(new DatabaseSource(providerFactory, connectionString, commandText));
+
+ ///
+ /// Load an from a database using a .
+ /// Note that 's are lazy, so no actual loading happens here, just schema validation.
+ ///
+ /// Defines the schema of the data to be loaded. Use public fields or properties
+ /// decorated with (and possibly other attributes) to specify the column
+ /// names and their data types in the schema of the loaded data.
+ /// The catalog.
+ /// The factory used to create the .
+ /// The string used to open the connection.
+ /// The text command to run against the data source.
+ /// The timeout (in seconds) for the database command.
+ /// The data view.
+ public static IDataView LoadFromDatabase(this DataOperationsCatalog catalog,
+ DbProviderFactory providerFactory, string connectionString, string commandText, int commandTimeoutInSeconds)
+ => catalog.LoadFromDatabase(new DatabaseSource(providerFactory, connectionString, commandText, commandTimeoutInSeconds));
}
}
diff --git a/test/Microsoft.ML.Tests/DatabaseLoaderTests.cs b/test/Microsoft.ML.Tests/DatabaseLoaderTests.cs
index 2c70e5a9cb..32201d82e4 100644
--- a/test/Microsoft.ML.Tests/DatabaseLoaderTests.cs
+++ b/test/Microsoft.ML.Tests/DatabaseLoaderTests.cs
@@ -127,6 +127,53 @@ public void IrisLightGbmWithLoadColumnName()
}).PredictedLabel);
}
+ [X86X64FactAttribute("The SQLite un-managed code, SQLite.interop, only supports x86/x64 architectures.")]
+ public void LoadFromDatabaseLoadsExpectedData()
+ {
+ // Use an in-memory SQLite database so the test is fast and self-contained.
+ var connectionString = "DataSource=LoadFromDatabaseTest;Mode=Memory;Version=3;Timeout=120;Cache=Shared";
+ using (var connection = new SQLiteConnection(connectionString))
+ {
+ connection.Open();
+ using (var command = new SQLiteCommand(connection))
+ {
+ command.CommandText = """
+ BEGIN;
+ DROP TABLE IF EXISTS Iris;
+ CREATE TABLE IF NOT EXISTS Iris (Label INTEGER, SepalLength REAL, SepalWidth REAL, PetalLength REAL, PetalWidth REAL);
+ INSERT INTO Iris VALUES (0, 4.5, 5.6, 0.5, 0.5);
+ INSERT INTO Iris VALUES (1, 4.9, 2.4, 3.3, 1.0);
+ COMMIT;
+ """;
+ command.ExecuteNonQuery();
+ }
+
+ var mlContext = new MLContext(seed: 1);
+
+ // LoadFromDatabase combines CreateDatabaseLoader() and Load(DatabaseSource)
+ // into a single call. Exercise both the DatabaseSource overload and the
+ // DbProviderFactory arguments overload; both should load identical data.
+ var source = new DatabaseSource(SQLiteFactory.Instance, connectionString, "SELECT * FROM Iris");
+ var loadedFromSource = mlContext.Data.LoadFromDatabase(source);
+ var loadedFromArgs = mlContext.Data.LoadFromDatabase(SQLiteFactory.Instance, connectionString, "SELECT * FROM Iris");
+
+ foreach (var data in new[] { loadedFromSource, loadedFromArgs })
+ {
+ var rows = mlContext.Data.CreateEnumerable(data, reuseRowObject: false).ToArray();
+
+ rows.Length.Should().Be(2);
+
+ rows[0].Label.Should().Be(0);
+ rows[0].SepalInfo.Should().Equal(4.5f, 5.6f);
+ rows[0].PetalInfo.Should().Equal(0.5f, 0.5f);
+
+ rows[1].Label.Should().Be(1);
+ rows[1].SepalInfo.Should().Equal(4.9f, 2.4f);
+ rows[1].PetalInfo.Should().Equal(3.3f, 1.0f);
+ }
+ }
+ }
+
[LightGBMFact]
public void IrisVectorLightGbm()
{