Migrating to v6

Overview

Less is more is the theme for v6. No new big features were are added, and there were no rewrites of internal code, so you can consider it stable. The focus has been to maximize the longevity and reusability of the code. To this end, some features have been removed, although most of the breaking changes are removal of methods where an alternative exists, or removal of non-essential features.

The source code has also been re-organized so you can compile components independently.

General features

Removed strong name

The DbExtensions assembly is no longer strong named.

Target frameworks

v6 targets .NET 4.5, ending support for .NET 4.0. .NET Core 2.1 and .NET Standard 2.1 are supported starting v6.2.

Removed System.Data.Linq dependency

The mapping (metadata) classes from LINQ to SQL are now included in DbExtensions, although most of them are internal except the attributes ([Table], [Column], [Association]). Only attribute mapping is supported, no XML.

Removed extension methods

Most of the extension methods are gone, except those for IDataRecord. v5 had a lot of duplicated APIs, e.g. Map(this DbCommand command, ...) and Database.Map(...). Having two ways of doing the same thing is not only confusing, but also costly in terms of maintenance. Whether developing using extension methods is a good idea is also debatable. Having a centralized place where you can tweak things, e.g. configure profiling, is much better, and that is what Database provides.

So, if you can’t find the extension method, look in Database.

Depending on System.Data interfaces instead of System.Data.Common classes

Every reference to DbConnection, DbCommand, etc. has been replaced with IDbConnection, IDbCommand, etc.

Database

Removed named connection string support

ConfigurationManager is not available on .NET Core, so all dependencies on System.Configuration were removed. That means you can no longer use a named connection string, e.g.:

// this doesn't work anymore
var db = new Database("name=Northwind");

Instead you can use a new constructor and pass in the connection string and provider invariant name. Your application can still use ConfigurationManager on .NET Framework, e.g.:

ConnectionStringSetings connSettings = ConfigurationManager.ConnectionStrings["Northwind"];

var db = new Database(connSettings.ConnectionString, connSettings.ProviderName);

Removed dependency on DbCommandBuilder and added new configuration properties

DbExtensions relied on DbCommandBuilder for provider specific details, such as how to quote identifiers and what parameter prefix to use. This ensured maximum compatibility with providers. Sadly, DbCommandBuilder is not available on .NET Core. Instead, new configuration properties were added to DatabaseConfiguration, with defaults for popular providers like System.Data.SqlClient and MySql.Data.MySqlClient. A hibrid approach was finally decided: configuration properties are used for known providers, with a fallback on DbCommandBuilder for unknown providers.

Removed Affect* methods

Affect was a weird name to begin with. The Execute method now provides the same functionality. See the table below.

v5 v6
db.Affect(sql, 1) db.Execute(sql, affect: 1, exact: true)
db.Affect(sql, 1, AffectedRecordsPolicy.AllowLower) db.Execute(sql, affect: 1)
db.AffectOne(sql) db.Execute(sql, affect: 1, exact: true)
db.AffectOneOrNone(sql) db.Execute(sql, affect: 1)
db.Execute(sql) db.Execute(sql)

Execute throws the new ChangeConflictException class.

SqlBuilder

Removed superfluous overloads

Most SqlBuilder and SqlSet methods had two overloads, e.g. SELECT(string) and SELECT(string, params object[]). The overloads without the params array were added as an optimization to avoid creating array instances when not needed. However, it added a lot of noise to the API. Also, the optimization is now done by the C# compiler, so it’s not needed anymore.

Arrays in SqlBuilder and SqlSet are no longer special

SqlBuilder and SqlSet would automatically expand an array value as a list of parameters, e.g. WHERE("foo IN ({0})", (object)new[] { "a", "b", "c" }) was equivalent to WHERE("foo IN ({0}, {1}, {2})", "a", "b", "c"). This turned out to be problematic for a couple of reasons. First, sometimes a cast was required (like in the given example) so the array was not to be interpreted as the full params array. Second, if you had an array member in your model, e.g. binary columns that map to byte[], then you had to workaround this feature.

In v6 you have to call SQL.List to opt-in into this feature. See the SqlBuilder tutorial for more information.

Removed ToCommand method

Use Database.CreateCommand(SqlBuilder).

SqlSet

Removed public constructors

Since extension methods were removed and every command goes through Database now, use the From and From<TResult> methods to get an instance of SqlSet.

Find and Include extension methods are now instance methods

You no longer need to import the DbExtensions namespace to call Find and Include.

Removed Oracle and SQL Server 2008 support

These added complexity and were rarely used. However, I plan on adding support for pluggable formatters to make SqlSet extensible.

SqlTable

Removed ConcurrencyConflictPolicy enumeration

And the methods that used it. Behavior depends on DatabaseConfiguration properties.

Renamed SQL property and all SqlCommandBuilder methods

Instead having methods that looked like SqlBuilder methods, it now has methods with proper naming and casing, e.g. table.SQL.UPDATE_SET_WHERE(entity) becomes table.CommandBuilder.BuildUpdateStatementForEntity(entity).

© Max Toro Q.