{"id":3351,"date":"2015-03-11T13:00:20","date_gmt":"2015-03-11T13:00:20","guid":{"rendered":"http:\/\/writeasync.net\/?p=3351"},"modified":"2015-03-16T05:36:44","modified_gmt":"2015-03-16T05:36:44","slug":"from-sync-to-async-sql","status":"publish","type":"post","link":"http:\/\/writeasync.net\/?p=3351","title":{"rendered":"From sync to async: SQL"},"content":{"rendered":"<p>Previously I discussed some common sync scenarios using <a href=\"http:\/\/writeasync.net\/?p=2541\">network<\/a> and <a href=\"http:\/\/writeasync.net\/?p=2621\">file I\/O<\/a> and how they can be migrated to modern async patterns. Today I have an addendum about asynchronous programming with <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.data.sqlclient.sqlconnection(v=vs.110).aspx\">SQL connections<\/a>.<\/p>\n<p>Let me start by saying that async SQL programming in .NET is not actually new. The legacy async programming model (<code>IAsyncResult<\/code> and friends) has been supported <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.data.sqlclient.sqlcommand.beginexecutereader(v=vs.80).aspx\">since .NET 2.0<\/a> &#8212; check out these <a href=\"http:\/\/blogs.msdn.com\/b\/angelsb\/archive\/2004\/09\/02\/224964.aspx\">blasts<\/a> from the <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms379553\">past<\/a>. Async is even easier now in .NET 4.5 using the <code>Task<\/code>-based async methods of <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.data.sqlclient.sqlconnection.openasync(v=vs.110).aspx\">SqlConnection<\/a> and <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.data.sqlclient.sqlcommand.executereaderasync(v=vs.110).aspx\">SqlCommand<\/a> which as it happens are little more than wrappers around the existing Begin\/End methods. (They do have a true async Open call now, so <a href=\"http:\/\/www.tech-archive.net\/Archive\/DotNet\/microsoft.public.dotnet.framework.adonet\/2006-10\/msg00113.html\">that&#8217;s a relief<\/a>.) Consult the <a href=\"http:\/\/blogs.msdn.com\/b\/adonet\/archive\/2012\/04\/20\/using-sqldatareader-s-new-async-methods-in-net-4-5-beta.aspx\">ADO.NET<\/a> <a href=\"http:\/\/blogs.msdn.com\/b\/adonet\/archive\/2012\/07\/15\/using-sqldatareader-s-new-async-methods-in-net-4-5-beta-part-2-examples.aspx\">blog<\/a> for more details.<\/p>\n<p>Remember that <strong>asynchronous does not imply concurrent<\/strong>. You cannot issue multiple async commands in parallel against a single SqlConnection instance unless you enable <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/cfa084cz(v=vs.110).aspx\">Multiple Active Result Sets<\/a> (&#8220;MARS&#8221;). Of course, this comes with <a href=\"http:\/\/stackoverflow.com\/a\/624646\">its own set of caveats<\/a> and should not be used lightly.<\/p>\n<p>Alas, there are some more limitations. Firstly, SqlConnection works with a full blown <a href=\"http:\/\/www.microsoft.com\/en-us\/server-cloud\/products\/sql-server\/\">SQL Server<\/a> instance (that includes a local, remote, or even an <a href=\"http:\/\/azure.microsoft.com\/en-us\/services\/sql-database\/\">Azure instance<\/a>) but <em>not<\/em> <a href=\"https:\/\/msdn.microsoft.com\/en-us\/data\/ff687142.aspx\">SQL Server Compact Edition<\/a> or <a href=\"http:\/\/system.data.sqlite.org\/\">SQLite<\/a>. There are various techniques to <em>simulate<\/em> async by offloading work to the thread pool (e.g. <a href=\"https:\/\/github.com\/oysteinkrog\/SQLite.Net-PCL\/blob\/master\/src\/SQLite.Net.Async\/AsyncTableQuery.cs\">AsyncTableQuery<\/a> in the <a href=\"https:\/\/www.nuget.org\/packages\/SQLite.Net.Async-PCL\">SQLite.Net.Async PCL<\/a>) but apparently no <strong>true<\/strong> async implementations yet.<\/p>\n<p>Secondly, users of <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/bb386976(v=vs.110).aspx\">LINQ to SQL<\/a> should note that it uses synchronous APIs to do its work. However, there is a clever workaround to combine LINQ with async SQL <a href=\"http:\/\/www.hanselman.com\/blog\/TheWeeklySourceCode51AsynchronousDatabaseAccessAndLINQToSQLFun.aspx\">documented by Scott Hanselman<\/a>. The trick involves asking <code>DataContext<\/code> to convert the expression to a SqlCommand via <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.data.linq.datacontext.getcommand(v=vs.110).aspx\"><code>GetCommand<\/code><\/a> and then handling the execution explicitly using the async methods:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprivate static async Task LinqDemoAsync(string connectionString)\r\n{\r\n    using (SqlConnection connection = new SqlConnection(connectionString))\r\n    {\r\n        await connection.OpenAsync();\r\n        DataContext db = new DataContext(connection);\r\n        await GetRowAsync(db, 1);\r\n        await GetRowAsync(db, 2);\r\n        await GetRowAsync(db, 3);\r\n    }\r\n}\r\n\r\nprivate static async Task GetRowAsync(DataContext db, int id)\r\n{\r\n    Table&lt;Demo&gt; table = db.GetTable&lt;Demo&gt;();\r\n    var query = from r in table where r.Id == id select r;\r\n    Demo item = await QueryAsync(db, query);\r\n    Console.WriteLine(item);\r\n}\r\n\r\nprivate static async Task&lt;T&gt; QueryAsync&lt;T&gt;(DataContext db, IQueryable&lt;T&gt; query)\r\n{\r\n    using (SqlCommand command = (SqlCommand)db.GetCommand(query))\r\n    using (SqlDataReader reader = await command.ExecuteReaderAsync())\r\n    {\r\n        return db.Translate&lt;T&gt;(reader).First();\r\n    }\r\n}\r\n\r\n&#x5B;Table]\r\nprivate sealed class Demo\r\n{\r\n    &#x5B;Column]\r\n    public int Id { get; set; }\r\n\r\n    &#x5B;Column]\r\n    public string Name { get; set; }\r\n\r\n    public override string ToString()\r\n    {\r\n        return &quot;(&quot; + this.Id + &quot;, &quot; + this.Name + &quot;)&quot;;\r\n    }\r\n}\r\n<\/pre>\n<p>Now go forth and write async queries and inserts!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Previously I discussed some common sync scenarios using network and file I\/O and how they can be migrated to modern async patterns. Today I have an addendum about asynchronous programming with SQL connections. Let me start by saying that async&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21,91],"tags":[],"class_list":["post-3351","post","type-post","status-publish","format-standard","hentry","category-async","category-design"],"_links":{"self":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/3351","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3351"}],"version-history":[{"count":0,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/3351\/revisions"}],"wp:attachment":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3351"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}