Releases and Roadmap

MaceWindu edited this page Nov 17, 2018 · 128 revisions

Roadmap

Below is the list of some features on our radar for upcoming releases. Also check what is included into our release milestones.

Release Notes

For unreleased versions you can try implemented changes and fixes using MyGet feed, which contains latest development version.

MyGet

Release 2.6.0 (unreleased)

Packaging

  • added missing MSBUILD namepace to props files to fix Visual Studio 2015 compatibility (#1401)

LINQ

  • fixed issue with handling of Count function in subqueries (#873)

Mappings

Aliases and calculated fields support in fluent mapper (#1365, #1389)

With this change you can easily configure aliases, expression properties and calculated properties using fluent mapper (attribute-based mapper already had support for it):

  • lias means that some member is just an alias for another existing member in your mapping and when you query database using alias, Linq To DB should use member, referenced by alias.
  • expression property is a property, defined as some expression. When such property used in query, Linq To DB replace it with configured expression
  • calculated property is an expression property, that additionally filled in with value on entity materialization.
interface IEntity
{
    int    Id             { get; set; }
    int    Value          { get; set; }
    string ValueWithId    { get; set; }
    string ValueWithoutId { get; set; }
}

class Entity : IEntity
{
    int    Id              { get; set; }
    int    Value           { get; set; }
    string ValueWithId     => Id + Value; // calculated property in C#
    string ValueWithoutId  { get; set; }

    public int    EntityId { get => Id; set => Id = value; }
}

MappingSchema.Default.GetFluentMappingBuilder().Entity<Entity>()
    .Property(e => e.Id) // column Id
    .Property(e => e.Value) // column Value
     // Alias: EntityId is just an alias for Id property
    .Member(e => e.EntityId).IsAlias(e => e.Id)
     // Calculated property
     // in generated SQL will be replaced with "t.Id + t.Value"
    .Member(e => e.ValueWithId).IsExpression(e => e.Id + e.Value)
     // Materialized calculated property
     // in generated SQL will be replaced with "t.Value - t.Id"
     // during materialization, will select value of expression into property
    .Member(e => e.ValueWithId).IsExpression(e => e.Value - e.Id, true);

List of new APIs:

EntityMappingBuilder
  • Member(Expression propertyOrFieldSelector) - defines mapping member of entity
PropertyMappingBuilder
  • Member(Expression propertyOrFieldSelector) - defines mapping member of entity
  • IsAlias(Expression aliasedMemberSelector) - marks mapping member as alias using expression
  • IsAlias(string aliasedMember) - marks mapping member as alias using target member name
  • IsExpression(Expression expression, bool materialized = false) - marks mapping member as calculated property using expression (with or without materialization)

Merge API

  • fixed issue where Linq To DB could use parameter value from parallel MERGE query, if same query (with different parameters) executed in parallel on another thread (#1398)

Provider-specific changes

SAP/Sybase ASE
  • linq2db.Sybase.DataAction nuget package AdoNetCore.AseClient dependency version bumped to 0.13.0. This version contains fixes to remaining issues, discovered during Linq To DB testing with this provider.

Release 2.5.2

  • contains important fix to UNION queries regression, introduced in 2.4.0 (#1347)

Release 2.5.1

Small bugfix release to address:

  • Several CTE issues, reported by users (#1284, #1380).
  • PostgreSQL procedure schema reader to work with npgsql 4.x (#1382)
  • Fix ODP.NET Oracle provider discovery from GAC (#1384)

Release 2.5.0

LINQ

  • fixed LinqException("Sequence '{0}' cannot be converted to SQL") when LINQ expression use client-side methods with lambda parameters (#1316)
Support for lambda expression parameters in query expressions

You can use lambda expression parameters for query composition in LINQ expressions using Compile method call (#1343).

public IQueryable<T> SampleQuery<T>(Expression<Func<T, bool>> filter)
{
    return from record in _db.GetTable<T>
        // add Compile() call here to make code compilable
        // and Linq To DB will interpret it correctly
        where filter.Compile()(record)
        select record;
}

SQL Generation

  • fixed CTE name generation in expressions with multiple CTEs (#1340)
  • fixed incorrect CTE RECURSIVE keyword placing in expressions with multiple CTEs (#1340)
  • fixed issues with CTE ordering in expressions with multiple CTEs (#1340)
  • fixed invalid SQL generation for CTE combined with COUNT (#1348)
  • fixed incorrect detection of parameters in sub-queries (#1363)
  • fixed issue with recursive CTE with nesting (#1361)

T4 and Schema

  • fixed issue with incorrect name generation for generic classes and methods with duplicate names (#1346)

Mappings

  • fixed support of members with new modifier (#1313)
  • fixed missing sbyte type handling (#1351)

Packaging

  • minimal System.Data.SqlClient dependency bumped to v4.5.1 (#1342)

Other changes

  • added Completed trace event to DataReader\DataReaderAsync (#1358)
  • added StartTime property to all trace events to provide operation start time in UTC (#1368)
  • added ExecutionTime property to all trace events except BeforeExecute event to provide elapsed time since operation start (#1368)
  • fixed trace event's ExecutionTime property having invalid value if DST shift occured between operation start and generated trace event (#1368)
  • updating DataConnection.CommandTimeout will update existing CommandTimeout for associated DbCommand instance (#1354)
  • added new events DataConnection.OnConnectionOpened and DataConnection.OnConnectionOpenedAsync (#1372). Those events triggered when database connection opened using synchonous or asynchronous API and could be used to perform some connection initialization logic. E.g. you can use it with SQLite to configure encryption keys

Provider-specific changes

SQL CE
  • add new option SqlCeConfiguration.InlineFunctionParameters to force function parameters inlining to support SQL CE 3.0 (#1350)
SQL Server
  • fixed issue with duplicate column entry in table schema when column participate in index and both index and column have description (#1144)
  • enabled UDT support for netstandard2.0 build (#1349)

Release 2.4.0

LINQ

  • fixed InvalidCastException exception when LinqExtensions join methods builder tried to parse Queryable join methods (#1209, #1324)
  • fixed exception on use of dynamic columns feature with UNION queries (#1319)

SQL Generation

  • add duplicate parameters detection for all providers except providers with positional parameters (Informix) (#1315)
  • fixed incorrect optimization of selected fields for UNION sub-queries (#1222)
  • fixed comparison of Nullable<T> properties with null
  • fixed IDataContext.InlineParameters = true flag to be honored by byte[]-typed parameters (System.Linq.Data.Binary-typed parameters already worked) (#1304)

T4

  • fixed code generation for procedure/function with name, used by C# keyword (#1295)
  • fixed namespaces generation to take into account types, used by procedure/function parameters (#1295)
  • fixed Sql.FunctionAttribute.Name generation to include schema/owner if it is not default schema (#1328)

Mappings

Table column ordering for create (#1305)

This feature allows you to specify how columns will be ordered in CREATE TABLE statement.

To specify column order using mapping attributes you can use ColumnAttribute.Order property:

[Table]
public class Table
{
    [Column(Order = 1)]
    public int ID { get; set; }

For fluent mapping you should use PropertyMappingBuilder.HasOrder(order) method:

db.MappingSchema.GetFluentMappingBuilder()
    .Entity<Table>()
        .Property(t => t.ID)
            .HasOrder(1);

Columns ordered using following rules:

  • first columns with non-negative order in ascending order
  • second columns without order specified in arbitrary order
  • last columns with negative order in ascending order

E.g.

Column order configuration:
Column1.Order = 1
Column2.Order = 10
Column3.Order = -1
Column4.Order = -10
Column5.Order = null (unspecified)

Order in CREATE TABLE:
Column1(1), Column2(10), Column5(unspecified), Column4(-10), Column5(-1)

Provider-specific changes

Access
  • add support for binary literals for byte[] and System.Linq.Data.Binary types (#1304)
DB2
  • add support for binary literals for byte[] and System.Linq.Data.Binary types (#1304)
Firebird
  • add support for byte[] and System.Linq.Data.Binary fields in CreateTable() using BLOB type (#1304)
  • add support for binary literals for byte[] and System.Linq.Data.Binary types (#1304)
MySQL/MariaDB
  • add support for binary literals for byte[] and System.Linq.Data.Binary types (#1304)
Oracle
  • linq2db.Oracle.Managed nuget package dependency for netstandard2.0 projects updated to release version (2.18.3) of Oracle.ManagedDataAccess.Core (#1329)
  • add support for binary literals for byte[] and System.Linq.Data.Binary types using HEXTORAW function (#1304)
PostgreSQL
  • add support for binary literals for byte[] and System.Linq.Data.Binary types (#1304)
  • fixed issue with generation of properties/parameters of object type instead of Npgsql*Type type by T4 model generator (#1331)
SAP HANA
  • add support for binary literals for System.Linq.Data.Binary type (#1304)
SQL Sever CE
  • add support for binary literals for byte[] and System.Linq.Data.Binary types (#1304)
SQLite
  • add support for binary literals for byte[] and System.Linq.Data.Binary types (#1304)
Sybase/SAP ASE
  • stopped generating N prefix for string literals as it doesn't have special meaning in ASE and conflicts with u& prefix (#1300)
  • linq2db.Sybase.DataAction nuget package AdoNetCore.AseClient dependency version bumped to 0.11.0. We recommed to use this version (or higher) as it contains fixes to most of issues, discovered during Linq To DB testing with this provider (remaining issues will be fixed with 0.12 release).
  • add support for binary literals for byte[] and System.Linq.Data.Binary types (#1304)

Release 2.3.0

LINQ

  • fixed support for dynamic properties in DML operations (#1268)
  • enabled use of default value (default(T)) for dynamic property, if it doesn't have value in DynamicColumnsStore (#1268)
  • fixed handling of char? Property == '<SOME_CHAR>' pattern (#1287)

SQL Generation

  • fixed missing IS (NOT) NULL check in complex conditions over nullable fields (#1261)
  • added CanBeNull property to Sql.ExtensionAttribute to tell Linq To DB if it needs to generate extra check for NULL in comparison expressions. Default value: true (#1292)

WCF Service

  • fixed serialization for double/decimal nullable values to allways use invariant culture format (#1290)
  • apply provider's ExecutionScope method to WCF queries (#1290)

T4

  • updated T4 templates instructions to create new template file instead of copying of sample template, as it doesn't work with new project types (#1194)
  • added new nuget package linq2db.SQLite.MS, which references Microsoft.Data.Sqlite.Core package instead of System.Data.SQLite.Core (#1175)

Mappings

  • removed sealed keyword from PrimaryKeyAttribute and NotNullAttribute mapping attributes (#1281)

Merge API

Merge hints support (#1273)

Added MERGE statement hints support for providers, that support them: Informix, Oracle, MS SQL. Hints could be specified using new overrides to Merge and MergeInto methods with additional string hint parameter.

Below you can find examples how to use API and generated SQL.

Sql Server

Hint applied to merge target (OPTIONS clause still not supported). Example:

db.TargetTable
    .Merge("HOLDLOCK")
    .UsingTarget()
    .OnTargetKey()
    .UpdateWhenMatched()
    .Merge();
MERGE INTO [TargetTable] WITH(HOLDLOCK) [Target] ....
Oracle
db.TargetTable
    .Merge("append")
    .UsingTarget()
    .OnTargetKey()
    .UpdateWhenMatched()
    .Merge();
MERGE /*+ append */ INTO TestMerge1 Target ...
Informix
db.TargetTable
    .Merge("AVOID_STMT_CACHE")
    .UsingTarget()
    .OnTargetKey()
    .UpdateWhenMatched()
    .Merge();
MERGE {+ AVOID_STMT_CACHE } INTO TestMerge1 Target ...

Other changes and fixes

  • added SourceLink support (#1217)
  • linq2db.t4models nuget package updated to work with latest linq2db version (#1251)

Provider-specific changes

Informix
Merge hints support (#1273)

See description above in Merge API section.

New option to control TO_DATE fractional seconds formatting (#1265)

Starting from Informix releases v11.70.xC8 and v12.10.xC2 IBM changed behavior of %F directive. To support both old and new behavior, new option was introduced:

// set it to true, if you use v11.70.xC8/v12.10.xC2
// or newer release on Informix database
LinqToDB.DataProvider.Informix
    .InformixConfiguration.ExplicitFractionalSecondsSeparator = false;

Having this option configured incorrectly will result in ERROR [HY000] [Informix .NET provider][Informix]Missing decimal point in datetime or interval fraction. error from Informix for queries with DateTime literals with fractional second values.

MS SQL
Oracle
  • merge hints support (#1273). See description above in Merge API section.
SQLite
  • added new nuget package linq2db.SQLite.MS, which references Microsoft.Data.Sqlite.Core package instead of System.Data.SQLite.Core (#1175)
  • added workaround for bug in Microsoft.Data.Sqlite provider, when it saves char value as string with character code instead of just a string to database if you pass it as parameter (#1279)

Release 2.2.0

Documentation

LINQ

  • added support for null checks using ternary operator like p ==/!= null ? p.SomeProperty : null (#1202)

    Note: you don't need to use this pattern in your code with LinqToDB.

    p.SomeProperty/(StructType?)p.SomeStructProperty will work just fine.

  • added proper support of Nullable<T>.HasValue property (#1213)

  • added support for expressions that could return DataParameter | null type

  • added support for AsQueryable() method use in queries, e.g. on IGrouping<,> value (#1225)

SQL Generation

  • fixed incorrect query generation for full outer join of sub-queries with filters when sub-query filter were moved to join condition (#1210, #426, #437, #1218)
  • fixed incorrect comparison generation for nullable primary key columns in MERGE ON conditions for InsertOrReplace, InsertOrUpdate and Merge API's OnTargetKey methods (#1238)
ORDER BY with DISTINCT support

Fixed bad SQL generation for queries with ORDER BY and DISTINCT when sorted column not selected by query for providers that doesn't support such queries (#1221).

Now it will convert query to use GROUP BY instead of DISTINCT. You can disable this functionality using following option:

// query transformation enabled by default
Configuration.Linq.KeepDistinctOrdered = false;

When you disable this option, LinqToDB will remove columns, not selected by query, from ORDER BY clause.

Affected providers:

  • Access
  • DB2
  • Informix
  • Oracle
  • PostgreSQL
  • SAP HANA
  • SQL Server CE
  • SQL Server
  • Sybase/SAP ASE

T4 Templates

  • fixed generation of classes and functions names for tables, views and functions with duplicate names. This could happen when you don't use GenerateSchemaAsType = true; generation option and generate objects for all schemas in single class (#1191)
  • fixed generation of function parameters and association properties names if they use C# keyword for name (#1205)
  • added initial support for custom aggregate functions generation (#1184). Right now only schema provider for PostgreSQL returns such functions. If you need this feature for some other provider, please create new feature request. In meantime, you can add aggregate function metadata to your T4 template manually
  • fixed GenerateSchemaAsType=true; option to generate separate type for schema without tables or views (function-only schemas). Before fix, such functions were generated in class for default schema (#1184)
  • added new InitMappingSchema method to generated code. This method will contain required MappingSchema registration code. For now this method used only for PostgreSQL model generation, but later we can use it for other providers, so if you don't use generated constructors, you should add call to this function to your custom constructors (#1184)
  • added missing generation of OUT stored procedure parameters (#1236)
  • fixed generation of stored procedures with table result to initialize OUT`INOUT` parameters with results after procedure call (#1237). Note that this will disable delayed execution of stored procedure till result enumeration.
  • fixed function name incorrectly prefixed with dot (.) when function has default schema (#1237)

Other changes and fixes

  • ITable<TEntity> interface implementation improved to initialize it's properties (name, schema, database name) from mapping schema on creation
  • fixed exception when async query used with RetryPolicy (#1174)
  • fixed binding of output parameters values for async call of stored procedure (#1223)

Provider-specific changes

DB2
  • improved support for client-side source columns that contain only null values in Merge (#1239)
  • specified default mappings to database types: DataType.Boolean -> smallint, DataType.Guid -> char(16) for bit data (#1239)
MySQL/MariaDB
  • fixed incorrect read of stored procedure metadata by SchemaProvider (with incorrect T4 model generated) if procedure has output parameters and doesn't return table results (#1237)
Oracle
Lowercase identifiers quotation changes

Previous versions of LinqToDB didn't quoted identifiers if they contain lowercase letters. This is not correct, because unquoted identifiers converted by Oracle to upper-case. It was causing issues for users with quoted identifiers with lower-case letters (#1243).

Starting from this release we will add new option to switch to proper quotation mode:

OracleTools.DontEscapeLowercaseIdentifiers = true;

By default quotation mode set to true to support existing applications, but we recommend you to disable it and fix your mappings ASAP as we plan to remove this option in future releases.

Who will be affected by this change:

  • if you use model, generated by T4 templates, you don't need to fix your mappings as T4 already generates model with uppercase identifiers
  • if you defined your model manually, you need to check if identifiers in your mapping use lowercase letters and change them to uppercase

Example:

//[Table] // old mapping
[Table("TABLE1")] // fixed mapping
public class Table1
{
//    [Column] // old mapping
    [Column("ID")] // fixed mapping
    public int Id { get; set; }
}

//[Table("SomeTable")] // old mapping
[Table("SOMETABLE")] // fixed mapping
public class Table1
{
//    [Column("SomeColumn")] // old mapping
    [Column("SOMECOLUMN")] // fixed mapping
    public int Id { get; set; }
}
PostgreSQL
Functions support by SchemaProvider

PR, issues #1162, #1220.

This feature adds support for functions and procedures description load to PostgreSQL schema provider and support for PostgreSQL functions generation by T4 model.

What it includes:

  • loading metadata for functions and procedures by schema provider
  • generation of functions by T4 model including functions with output parameters, void functions and aggregates (see details below)

What is not supported:

  • procedures (PostgreSQL 11+) generation by T4 templates. It could work, but it wasn't tested as v11 is not released yet. Feel free to fill new issue if it doesn't work
  • generation of functions with dynamic results by T4 like json_to_record or json_to_recordset. Such functions need support from LinqToDB and could be added on request

Because PostgreSQL didn't have stored procedures prior to version 11, it had support for some features in functions, that usually implemented by procedures in other databases. For those features we need to generate code by T4 in special way.

Void functions. Those are functions that doesn't return anything, but still have function semantic. This means you should be able to call such function in a place where you can call normal function. Because C# doesn't allow you to call void function in context, where it expected to have some result returned, we generate such functions using following signature:

[Sql.Function("some_void_function", ServerSideOnly = true)]
public static object SomeVoidFunction(/*input parameters*/)
    => throw new InvalidOperationException();

Note that generated function has object return type. It will allways return default value (null), Take into account that for PostgreSQL VOID = NULL will result in false, so don't try to make decisions on return value in your queries for such functions.

Functions with OUT/INOUT parameters. Because output parameters is a feature for stored procedures and functions should return data only using return value, PostgreSQL return such parameters as a single return value of record type, which contains all output parameter values. LinqToDB also don't break function semantics here and generate such functions in following way:

[Sql.Function("test_parameters", ServerSideOnly = true)]
public static TestParametersResult TestParameters(int? param1, int? param2)
    => throw new InvalidOperationException();

public class TestParametersResult
{
	public int? param2 { get; set; }
	public int? param3 { get; set; }
}

As you can see we generate separate POCO class to store values for output parameters. Because npgsql provider returns record values as object[], we need to register mapping from object[] to POCO class in mapping schema. This is done by InitMappingSchema method in generated code. If you don't use constructors, generated by T4, you need to call this method from your custom constructors.

SQL Server
  • fixed dialect detection logic to use database compatibility level instead of server version when it is not specified explicitly (#1204)

Release 2.1.0

Schema Provider Changes

  • Updated schema provider to skip foreign keys that reference columns, not available in schema. Fixes Access schema provider failure, when JET provider fails to return columns for some system tables, but returns foreign keys with references to those columns (#1164)
  • Fixed trailing underscore in member name for associations if foreign key column ends with _id suffix (#1173)

T4 Templates

  • fixed v2.0 regression in class/property names generation from table and column names, where names like 'SomeName'/SomeName_OtherName were converted to Somename/SomenameOthername instead of SomeName/SomeNameOtherName (#1161)

Extensions

  • fixed too aggressive caching of parameters, added to query by extension builders (#1177)

Other changes and fixes

  • Added new GetDataProvider API to DataConnection class to get data provider instance by provider name, configuration name and connection string
  • fixed bug with association predicate expression that could lead to various errors (#975, #1195, #1196)
Prefix query hints support

Added support for query hints, added before query. To add such hint, you need to start it with **.

Postfix hints example (SQL Server):

// adds suffix OPTION(RECOMPILE) hint only to next query
db.NextQueryHints.Add(SqlServerTools.Sql.OptionRecompile);

// adds suffix OPTION(RECOMPILE) hint to all queries
db.QueryHints.Add(SqlServerTools.Sql.OptionRecompile);

Prefix hints example (EXPLAIN modifier for MySQL):

// adds prefix EXPLAIN only to next query
db.NextQueryHints.Add("**EXPLAIN ");

// adds prefix EXPLAIN to all queries
db.QueryHints.Add("**EXPLAIN ");

Provider-specific changes

DB2
  • CTE support enabled
Firebird
  • added recursive CTE support (#1168)
MySQL
  • added recursive CTE support (#1168)
Oracle
  • Added support for Oracle NVARCHAR2 type (#633). Note that default mapping will map System.String to VARCHAR type for backward compatibility. To use NVARCHAR2 type, you need to specify proper type in your column mapping using DataType.NVarChar enumeration value or override default mapping for System.String in your MappingSchema:
// set default string mapping
MappingSchema.Default.SetDataType(
    typeof(string),
    new SqlDataType(DataType.NVarChar, typeof(string), 255));
PostgreSQL
  • added recursive CTE support (#1168)
SAP HANA
  • Fixed provider assembly discovery when referenced from GAC (#239)
SAP/Sybase ASE
DataAction AdoNetCore.AseClient provider support

Added support for fully managed provider with .NET Core support from DataAction. To use new provider you just need to add reference to this provider to your project instead of official provider and LINQ To DB will start to use it.

If you want to use both providers at the same time, you will need to explicitly specify provider using provider name AdoNetCore.AseClient or Sybase.Managed.

New T4 model generator nuget package linq2db.Sybase.DataAction created for this provider.

We would recommend to use post-0.10.1 DataAction provider when it will be released as we discovered several issues during integration and fixes for them were not yet released when those notes created. Or you can build provider from master branch to get version with latest fixes.

Other fixes
  • InvalidCastException from ASE native provider when loading schema for some procedure parameters. LINQ To DB will not use provider's functionality to load parameters metadata. Note that such parameters will have their direction properties (IsIn, IsOut, IsResult) set to false (#1060)
  • disable quotation for columns with name starting from # (#1064)

Release 2.0.0

Release Notes 2.0.0

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.