.NET Framework vs. .NET standard

The LLBLGen Pro Runtime framework supports both .NET Framework (.NET 4.5.2 or higher) and .NET Standard 2.0 or higher (from now on referred to as '.NET Standard'). The LLBLGen Pro Runtime Framework build for .NET Standard 2.0+ is the build to use for .NET Core 2.0+ / .NET 5+, Xamarin and other platforms other than .NET Framework. Not all databases are supported on .NET Standard 2.0+ and therefore not all DQEs are available for .NET Standard 2.0+. Almost all features are supported on both .NET Framework and .NET Standard, with a few differences, which are described below.

For more information about .NET Standard and how it relates to .NET Framework and .NET Core, please see the Microsoft documentation section on .NET Standard. Rule of thumb: for .NET Core/.NET 5+, use the .NET Standard build, for .NET Framework use the regular build for .NET Framework. The NuGet package contains both and should automatically take care of referencing the right version.

Info

It's recommended to use the .NET Framework build of the LLBLGen Pro runtime framework on .NET Framework and the .NET Standard build on .NET Core/.NET 5+, even though .NET Framework supports .NET Standard as well. If you're referencing the runtime libraries through nuget, this is automatic.

Important!

When using .NET Standard be aware that there are no .config files: all configuration is done through code, using the RuntimeConfiguration system. This includes connection strings and other settings you might need at runtime.

Assembly location

The .NET Framework builds of the LLBLGen Pro Runtime Framework assemblies are found in the folder: llblgen pro installation folder\Frameworks\LLBLGen Pro\RuntimeLibraries\CompiledRuntimeLibraries. The .NET Standard builds can be found in the folder llblgen pro installation folder\Frameworks\LLBLGen Pro\RuntimeLibraries\CompiledRuntimeLibraries\Netstandard2.0.

It's recommended however you use the Nuget packages. See for more information Compiling the code.

Features not supported in the .NET Standard build

Almost all features are supported on .NET Standard, however there are some differences and caveats, which are described below.

  • Configuration of certain parts of the runtime has to be done through the RuntimeConfiguration system, instead of the .config file.
  • Auto-discovery of Dependency Injection types in assemblies from disk and the current appdomain isn't available on .NET Standard. Instead you always have to specify the particular assembly/assemblies directly which is then probed for instance types. This is done through the RuntimeConfiguration system.
  • Due to the fact that System.Type (through its runtime equivalent RuntimeType) in CoreCLR v2.0 isn't marked as Serializable, the data created by binary serializing entities, contains different data on .NET core than it does on .NET Framework, as we had to serialize type instances as strings (the full name of the type). This means that if you binary serialize entity graphs on .NET Core and deserialize them on .NET Framework, it won't work. This is a limitation of .NET Core 2.0 and by design.
  • BinarySerialization is there, but the support for serializable types in .NET core 2.0 is still low. It is likely you'll run into a type that's not serializable when using it. We tried to port our code to types which are serializable so the issues don't occur with types in our runtime but we can't guarantee that code which serializes properly on .NET Framework will serialize properly as well on .NET core 2.0. E.g. binary serializing a TypedList / TypedView based on a DataTable, and they contain a DBNull, will fail on .NET Core, because DBNull isn't serializable on .NET Core. This is a limitation in .NET Core 2.0+.
  • Not all databases are supported on .NET Standard across all supported target platforms for .NET Standard, as not all databases have a 100% usable ADO.NET Provider for .NET Standard on all platforms. See below for details.
  • System.Transactions.TransactionScope, while supported by our code, won't work at runtime as it's not implemented in SqlClient on .NET core: it will throw an exception at runtime in SqlConnection. This is a limitation of .NET Core 2.0+. This will change in the future with the Microsoft.Data.SqlClient ADO.NET provider, but it's not clear when.

Databases supported on .NET Standard

All databases supported by the LLBLGen Pro Runtime framework are supported on .NET Framework. On .NET Standard not all databases have a usable ADO.NET provider so these databases are not supported. If a database receives a proper ADO.NET provider for .NET Standard, we'll add support for that database in an update.

Important!

No ADO.NET provider is available by default, you have to add the nuget package for the particular ADO.NET provider you want to use yourself, in all cases, including SqlClient.

The following databases are supported by the LLBLGen Pro Runtime Framework on .NET Standard 2.0+:

  • SQL Server, through Microsoft's own SqlClient package System.Data.SqlClient, or Microsoft.Data.SqlClient.
  • PostgreSql, through the Npgsql package
  • Firebird, through Firebird Client package
  • MySQL, through Devart's dotConnect for MySQL. The version required for .NET Standard/core isn't free, but there's no alternative. We can't use MySQL's own connector as it's GPL licensed.
  • IBM DB2, through the IBM DB2 data server provider.
  • Oracle, through the ODP.NET managed provider core, v2.18+.
  • MS Access, through the System.Data.OleDb package, v5.0 or higher. You still need a proper MS Access driver with OleDb, which are all Windows only. For Linux, System.Data.Odbc is required, but this hasn't been tested with our runtime.

Microsoft.Data.SqlClient

The open source ADO.NET provider Microsoft.Data.SqlClient is supported on both .NET Framework and .NET Standard, however for .NET Framework you have to use the RuntimeConfiguration system to specify the DbProviderFactory as by default the DbProviderFactory for Microsoft.Data.SqlClient isn't registered and the default System.Data.SqlClient will be used.

Important!

When specifying the factory from Microsoft.Data.SqlClient, you don't need to specify a different invariant name. By not specifying the invariant name, you'll make sure the DQE will use the default, like the code below:

// Configure the DQE
RuntimeConfiguration.ConfigureDQE<SQLServerDQEConfiguration>(
                    c => c.SetTraceLevel(TraceLevel.Verbose)
                            .AddDbProviderFactory(typeof(Microsoft.Data.SqlClient.SqlClientFactory))
                            .SetDefaultCompatibilityLevel(SqlServerCompatibilityLevel.SqlServer2012));

This way you'll make sure the DQE uses the default invariant name for the SQL Client factory, System.Data.SqlClient.