I have been experimenting with a lightweight solution for handling my business logic. It consists of a vanilla ADO.NET connection that is extended with Dapper, and monitored by Glimpse.ADO. The use case for this setup will be a web application that has to process a handful of queries asynchronously per request. Below a simple implementation of my setup in an MVC controller.
public class CatsAndDogsController : Controller
{
public async Task<ActionResult> Index()
{
var fetchCatsTask = FetchCats(42);
var fetchDogsTask = FetchDogs(true);
await Task.WhenAll(fetchCatsTask, fetchDogsTask);
ViewBag.Cats = fetchCatsTask.Result;
ViewBag.Dogs = fetchDogsTask.Result;
return View();
}
public async Task<IEnumerable<Cat>> FetchCats(int breedId)
{
IEnumerable<Cat> result = null;
using (var connection = CreateAdoConnection())
{
await connection.OpenAsync();
result = await connection.QueryAsync<Cat>("SELECT * FROM Cat WHERE BreedId = @bid;", new { bid = breedId });
connection.Close();
}
return result;
}
public async Task<IEnumerable<Dog>> FetchDogs(bool isMale)
{
IEnumerable<Dog> result = null;
using (var connection = CreateAdoConnection())
{
await connection.OpenAsync();
result = await connection.QueryAsync<Dog>("SELECT * FROM Dog WHERE IsMale = @im;", new { im = isMale });
connection.Close();
}
return result;
}
public System.Data.Common.DbConnection CreateAdoConnection()
{
var sqlClientProviderFactory = System.Data.Common.DbProviderFactories.GetFactory("System.Data.SqlClient");
var dbConnection = sqlClientProviderFactory.CreateConnection();
dbConnection.ConnectionString = "SomeConnectionStringToAwesomeData";
return dbConnection;
}
}
I have some questions concerning the creation of the connection in the CreateAdoConnection()
method. I assume the following is happening behind the scenes.
The call to sqlClientProviderFactory.CreateConnection()
returns an instance of System.Data.SqlClient.SqlConnection
passed as a System.Data.Common.DbConnection
. At this point Glimpse.ADO.AlternateType.GlimpseDbProviderFactory
kicks in and wraps this connection in an instance of Glimpse.Ado.AlternateType.GlimpseDbConnection
, which is also passed as a System.Data.Common.DbConnection
. Finally, this connection is indirectly extended by the Dapper library with its query methods, among them the QueryAsync<>()
method used to fetch the cats and dogs.
The questions:
System.Data.Common.DbCommand
with this connection's CreateCommand()
method, and use it's async methods - will those calls internally always end up using the vanilla async implementations of these methods as Microsoft has written them for System.Data.SqlClient.SqlConnection
and System.Data.SqlClient.SqlCommand
? And not some other implementations of these methods that are actually blocking?System.Data.SqlClient.SqlConnection
directly? (So, without the Glimpse.ADO wrapper)GlimpseDbProviderFactory
wraps/decorates/proxies all the registered factories. We then pass any calls we get through to the factory we wrap (in this case SQL Server). In the case of CreateConnection()
we ask the inner factory we have, to create a connection, when we get that connection, we wrap it and then return it to the originating caller