Skip to content

Commit

Permalink
Add NET472 TFM with native support for ValueTask, IAsyncEnumerable<T>…
Browse files Browse the repository at this point in the history
… and IAsyncDisposable (#2890)
  • Loading branch information
MaceWindu committed Mar 13, 2021
1 parent 71e4d41 commit 8246efe
Show file tree
Hide file tree
Showing 71 changed files with 259 additions and 272 deletions.
1 change: 0 additions & 1 deletion Build/linq2db.Source.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
<Import Project="linq2db.Default.props" />

<PropertyGroup>
<TargetFrameworks>net45;net46;netstandard2.0;netcoreapp2.1;netstandard2.1;netcoreapp3.1</TargetFrameworks>
<Configurations>Debug;Release</Configurations>
</PropertyGroup>

Expand Down
35 changes: 18 additions & 17 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,18 @@ Solutions:

#### Source projects

| Project \ Target |.NET 4.5 |.NET 4.6 | .NET Standard 2.0 | .NET Core 2.1 | .NET Standard 2.1 | .NET Core 3.1 |
|-------------------------------------------------:|:-------:|:-------:|:-----------------:|:-------------:|:-----------------:|:-------------:|
| `.\Source\LinqToDB\LinqToDB.csproj` |||||||
| `.\Source\LinqToDB\LinqToDB.Tools.csproj` |||| | | |
| `.\Source\LinqToDB\LinqToDB.AspNet.csproj` || || | | |
| Project \ Target |.NET 4.5 |.NET 4.6 |.NET 4.7.2 | .NET Standard 2.0 | .NET Core 2.1 | .NET Standard 2.1 | .NET Core 3.1 |
|-------------------------------------------------:|:-------:|:-------:|:---------:|:-----------------:|:-------------:|:-----------------:|:-------------:|
| `.\Source\LinqToDB\LinqToDB.csproj` ||| | ||||
| `.\Source\LinqToDB\LinqToDB.Tools.csproj` ||| | | | | |
| `.\Source\LinqToDB\LinqToDB.AspNet.csproj` || | | | | | |

Preferred target defines:
- `NETFRAMEWORK` - `net45` and `net46` target ifdef
- `NETFRAMEWORK` - `net45`, `net46` and `net472` target ifdef
- `!NETFRAMEWORK` - `netstandard2.0` and newer target ifdef
- `NETCOREAPP` - `netcoreapp2.1` and `netcoreapp3.1` target ifdef
- `NETSTANDARD2_1PLUS` - `netstandard2.1` and `netcoreapp3.1` target ifdef
- `NATIVE_ASYNC` - ifdef with native support for `ValueTask`, `IAsyncEnumerable<T>` and `IAsyncDisposable` types

Other allowed target defines:
- `NETSTANDARD2_1` - `netstandard2.1` target ifdef
Expand All @@ -58,6 +59,7 @@ Other allowed target defines:
- `NETCOREAPP2_1` - `netcoreapp2.1` target ifdef
- `NET45` - `net45` target ifdef
- `NET46` - `net46` target ifdef
- `NET472` - `net472` target ifdef

Allowed debugging defines:
- `TRACK_BUILD`
Expand All @@ -66,17 +68,16 @@ Allowed debugging defines:

#### Test projects

| Project \ Target |.NET 4.7.2 | .NET Core 2.1 | .NET Core 3.1 | .NET 5.0 | Xamarin.Forms Android v8.1 |
|---------------------------------------------------:|:---------:|:-------------:|:-------------:|:--------:|:--------------------------:|
| `.\Tests\Base\Tests.Base.csproj` ||||| |
| `.\Tests\FSharp\Tests.FSharp.fsproj` ||||| |
| `.\Tests\Linq\Tests.csproj` ||||| |
| `.\Tests\Model\Tests.Model.csproj` ||||| |
| `.\Tests\Tests.Android\Tests.Android.csproj` | | | | ||
| `.\Tests\Tests.Benchmarks\Tests.Benchmarks.csproj` ||||| |
| `.\Tests\Tests.Playground\Tests.Playground.csproj` ||||| |
| `.\Tests\Tests.T4\Tests.T4.csproj` ||||| |
| `.\Tests\VisualBasic\Tests.VisualBasic.vbproj` ||||| |
| Project \ Target |.NET 4.7.2 | .NET Core 2.1 | .NET Core 3.1 | .NET 5.0 |
|---------------------------------------------------:|:---------:|:-------------:|:-------------:|:--------:|
| `.\Tests\Base\Tests.Base.csproj` |||||
| `.\Tests\FSharp\Tests.FSharp.fsproj` |||||
| `.\Tests\Linq\Tests.csproj` |||||
| `.\Tests\Model\Tests.Model.csproj` |||||
| `.\Tests\Tests.Benchmarks\Tests.Benchmarks.csproj` |||||
| `.\Tests\Tests.Playground\Tests.Playground.csproj` |||||
| `.\Tests\Tests.T4\Tests.T4.csproj` |||||
| `.\Tests\VisualBasic\Tests.VisualBasic.vbproj` |||||


Allowed target defines:
Expand Down
3 changes: 3 additions & 0 deletions NuGet/linq2db.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
<dependencies>
<group targetFramework=".NETFramework4.5" />
<group targetFramework=".NETFramework4.6" />
<group targetFramework=".NETFramework4.7.2">
<dependency id="Microsoft.Bcl.AsyncInterfaces" version="5.0.0" />
</group>
<group targetFramework=".NETStandard2.0">
<dependency id="Microsoft.CSharp" version="4.7.0" />
<dependency id="System.ComponentModel.Annotations" version="5.0.0" />
Expand Down
8 changes: 4 additions & 4 deletions Source/LinqToDB/Async/AsyncDbConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public virtual string ConnectionString

public virtual IDbConnection Connection => _connection;

#if NETFRAMEWORK
#if !NATIVE_ASYNC
public virtual Task<IAsyncDbTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default)
=> Task.FromResult(AsyncFactory.Create(BeginTransaction()));
#elif !NETSTANDARD2_1PLUS
Expand Down Expand Up @@ -67,7 +67,7 @@ public virtual async ValueTask<IAsyncDbTransaction> BeginTransactionAsync(Isolat
}
return AsyncFactory.Create(BeginTransaction(isolationLevel));
}
#elif !NETFRAMEWORK
#elif NATIVE_ASYNC
public virtual ValueTask<IAsyncDbTransaction> BeginTransactionAsync(IsolationLevel isolationLevel, CancellationToken cancellationToken = default)
=> new ValueTask<IAsyncDbTransaction>(AsyncFactory.Create(BeginTransaction(isolationLevel)));
#else
Expand Down Expand Up @@ -129,7 +129,7 @@ public virtual void Dispose()
Connection.Dispose();
}

#if NETFRAMEWORK
#if !NATIVE_ASYNC
public virtual Task DisposeAsync()
{
Dispose();
Expand All @@ -143,7 +143,7 @@ public virtual ValueTask DisposeAsync()
return asyncDisposable.DisposeAsync();

Dispose();
return new ValueTask(Task.CompletedTask);
return default;
}
#endif

Expand Down
4 changes: 2 additions & 2 deletions Source/LinqToDB/Async/AsyncDbTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public virtual void Dispose()
Transaction.Dispose();
}

#if NETFRAMEWORK
#if !NATIVE_ASYNC
public virtual Task DisposeAsync()
{
Dispose();
Expand All @@ -63,7 +63,7 @@ public virtual ValueTask DisposeAsync()
return asyncDisposable.DisposeAsync();

Dispose();
return new ValueTask(Task.CompletedTask);
return default;
}
#endif

Expand Down
6 changes: 3 additions & 3 deletions Source/LinqToDB/Async/AsyncEnumeratorAsyncWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ namespace LinqToDB.Async
internal class AsyncEnumeratorAsyncWrapper<T> : IAsyncEnumerator<T>
{
private IAsyncEnumerator<T>? _enumerator;
#if NETFRAMEWORK
#if !NATIVE_ASYNC
private readonly Func<Task<Tuple<IAsyncEnumerator<T>, IDisposable?>>> _init;
private IDisposable? _disposable;
#else
private readonly Func<Task<Tuple<IAsyncEnumerator<T>, IAsyncDisposable?>>> _init;
private IAsyncDisposable? _disposable;
#endif

#if NETFRAMEWORK
#if !NATIVE_ASYNC
public AsyncEnumeratorAsyncWrapper(Func<Task<Tuple<IAsyncEnumerator<T>, IDisposable?>>> init)
#else
public AsyncEnumeratorAsyncWrapper(Func<Task<Tuple<IAsyncEnumerator<T>, IAsyncDisposable?>>> init)
Expand All @@ -26,7 +26,7 @@ public AsyncEnumeratorAsyncWrapper(Func<Task<Tuple<IAsyncEnumerator<T>, IAsyncDi

T IAsyncEnumerator<T>.Current => _enumerator!.Current;

#if NETFRAMEWORK
#if !NATIVE_ASYNC
async Task IAsyncDisposable.DisposeAsync()
{
await _enumerator!.DisposeAsync().ConfigureAwait(Common.Configuration.ContinueOnCapturedContext);
Expand Down
6 changes: 3 additions & 3 deletions Source/LinqToDB/Async/AsyncExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internal static class AsyncExtensions

var result = new List<T>();
var enumerator = source.GetAsyncEnumerator(cancellationToken);
#if NETFRAMEWORK
#if !NATIVE_ASYNC
await using (enumerator)
#else
await using (enumerator.ConfigureAwait(Common.Configuration.ContinueOnCapturedContext))
Expand Down Expand Up @@ -95,7 +95,7 @@ await using (enumerator.ConfigureAwait(Common.Configuration.ContinueOnCapturedCo
if (source == null) throw new ArgumentNullException(nameof(source));

var enumerator = source.GetAsyncEnumerator(cancellationToken);
#if NETFRAMEWORK
#if !NATIVE_ASYNC
await using (enumerator)
#else
await using (enumerator.ConfigureAwait(Common.Configuration.ContinueOnCapturedContext))
Expand All @@ -120,7 +120,7 @@ public static async Task<TSource> FirstAsync<TSource>(this IAsyncEnumerable<TSou
if (source == null) throw new ArgumentNullException(nameof(source));

var enumerator = source.GetAsyncEnumerator(token);
#if NETFRAMEWORK
#if !NATIVE_ASYNC
await using (enumerator)
#else
await using (enumerator.ConfigureAwait(Common.Configuration.ContinueOnCapturedContext))
Expand Down
38 changes: 18 additions & 20 deletions Source/LinqToDB/Async/AsyncFactory.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
using JetBrains.Annotations;
using LinqToDB.Common;
using LinqToDB.Expressions;
using LinqToDB.Extensions;
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using LinqToDB.Common;
using LinqToDB.Expressions;
using LinqToDB.Extensions;

namespace LinqToDB.Async
{
Expand All @@ -33,7 +31,7 @@ public static class AsyncFactory
private static readonly ConcurrentDictionary<Type, Func<IDbTransaction, IAsyncDbTransaction>> _transactionFactories
= new ConcurrentDictionary<Type, Func<IDbTransaction, IAsyncDbTransaction>>();

#if NETFRAMEWORK
#if !NATIVE_ASYNC
private static readonly MethodInfo _transactionWrap = MemberHelper.MethodOf(() => Wrap<IDbTransaction>(default!)).GetGenericMethodDefinition();
#else
#pragma warning disable CA2012 // ValueTask instances returned from method calls should be directly awaited...
Expand Down Expand Up @@ -103,7 +101,7 @@ private static async Task<IAsyncDbTransaction> Wrap<TTransaction>(Task<TTransact
return Create(await transaction.ConfigureAwait(Common.Configuration.ContinueOnCapturedContext));
}

#if !NETFRAMEWORK
#if NATIVE_ASYNC
private static async ValueTask<IAsyncDbTransaction> WrapValue<TTransaction>(ValueTask<TTransaction> transaction)
where TTransaction : IDbTransaction
{
Expand Down Expand Up @@ -131,15 +129,15 @@ private static async ValueTask<IAsyncDbTransaction> WrapValue<TTransaction>(Valu
// Availability:
// - DbTransaction (netstandard2.1, netcoreapp3.0)
// - Npgsql 4.1.2+
#if NETFRAMEWORK
#if !NATIVE_ASYNC
var disposeAsync = CreateDelegate<Func<IDbConnection , Task>, IDbConnection >(type, "DisposeAsync" , Array<Type>.Empty, Array<Type>.Empty, Array<Type>.Empty, true , false)
#else
var disposeAsync = CreateDelegate<Func<IDbConnection , ValueTask>, IDbConnection >(type, "DisposeAsync" , Array<Type>.Empty, Array<Type>.Empty, Array<Type>.Empty, true , true )
#endif
// Task DisposeAsync()
// Availability:
// - MySqlConnector 0.57+
#if NETFRAMEWORK
#if !NATIVE_ASYNC
?? CreateDelegate<Func<IDbConnection , Task>, IDbConnection >(type, "DisposeAsync" , Array<Type>.Empty, Array<Type>.Empty, Array<Type>.Empty, false, false);
#else
?? CreateDelegate<Func<IDbConnection , ValueTask>, IDbConnection >(type, "DisposeAsync" , Array<Type>.Empty, Array<Type>.Empty, Array<Type>.Empty, false, true );
Expand All @@ -162,7 +160,7 @@ private static async ValueTask<IAsyncDbTransaction> WrapValue<TTransaction>(Valu
// - (stub) DbConnection (netstandard2.1, netcoreapp3.0)
// - MySqlConnector 0.57+
// - Npgsql 4.1.2+
#if NETFRAMEWORK
#if !NATIVE_ASYNC
var beginTransactionAsync = CreateTaskTDelegate<Func<IDbConnection, CancellationToken , Task<IAsyncDbTransaction>>, IDbConnection, IDbTransaction>(type, "BeginTransactionAsync", _tokenParams , _transactionWrap, true, false)
#else
var beginTransactionAsync = CreateTaskTDelegate<Func<IDbConnection, CancellationToken , ValueTask<IAsyncDbTransaction>>, IDbConnection, IDbTransaction>(type, "BeginTransactionAsync", _tokenParams , _transactionValueWrap, true, true)
Expand All @@ -171,7 +169,7 @@ private static async ValueTask<IAsyncDbTransaction> WrapValue<TTransaction>(Valu
// Availability:
// - MySql.Data
// - MySqlConnector < 0.57
#if NETFRAMEWORK
#if !NATIVE_ASYNC
?? CreateTaskTDelegate<Func<IDbConnection, CancellationToken , Task<IAsyncDbTransaction>>, IDbConnection, IDbTransaction>(type, "BeginTransactionAsync", _tokenParams , _transactionWrap, false, false);
#else
?? CreateTaskTDelegate<Func<IDbConnection, CancellationToken , ValueTask<IAsyncDbTransaction>>, IDbConnection, IDbTransaction>(type, "BeginTransactionAsync", _tokenParams , _transactionValueWrap, false, true);
Expand All @@ -182,7 +180,7 @@ private static async ValueTask<IAsyncDbTransaction> WrapValue<TTransaction>(Valu
// - (stub) DbConnection (netstandard2.1, netcoreapp3.0)
// - MySqlConnector 0.57+
// - Npgsql 4.1.2+
#if NETFRAMEWORK
#if !NATIVE_ASYNC
var beginTransactionIlAsync = CreateTaskTDelegate<Func<IDbConnection, IsolationLevel, CancellationToken, Task<IAsyncDbTransaction>>, IDbConnection, IDbTransaction>(type, "BeginTransactionAsync", _beginTransactionParams, _transactionWrap, true, false)
#else
var beginTransactionIlAsync = CreateTaskTDelegate<Func<IDbConnection, IsolationLevel, CancellationToken, ValueTask<IAsyncDbTransaction>>, IDbConnection, IDbTransaction>(type, "BeginTransactionAsync", _beginTransactionParams, _transactionValueWrap, true, true)
Expand All @@ -191,7 +189,7 @@ private static async ValueTask<IAsyncDbTransaction> WrapValue<TTransaction>(Valu
// Availability:
// - MySql.Data
// - MySqlConnector < 0.57
#if NETFRAMEWORK
#if !NATIVE_ASYNC
?? CreateTaskTDelegate<Func<IDbConnection, IsolationLevel, CancellationToken, Task<IAsyncDbTransaction>>, IDbConnection, IDbTransaction>(type, "BeginTransactionAsync", _beginTransactionParams, _transactionWrap, false, false);
#else
?? CreateTaskTDelegate<Func<IDbConnection, IsolationLevel, CancellationToken, ValueTask<IAsyncDbTransaction>>, IDbConnection, IDbTransaction>(type, "BeginTransactionAsync", _beginTransactionParams, _transactionValueWrap, false, true);
Expand All @@ -217,15 +215,15 @@ private static async ValueTask<IAsyncDbTransaction> WrapValue<TTransaction>(Valu
// Availability:
// - (stub) DbConnection (netstandard2.1, netcoreapp3.0)
// - Npgsql 4.1.2+
#if NETFRAMEWORK
#if !NATIVE_ASYNC
var disposeAsync = CreateDelegate<Func<IDbConnection, Task >, IDbConnection>(type, "DisposeAsync", Array<Type>.Empty, Array<Type>.Empty, Array<Type>.Empty, true , false)
#else
var disposeAsync = CreateDelegate<Func<IDbConnection, ValueTask>, IDbConnection>(type, "DisposeAsync", Array<Type>.Empty, Array<Type>.Empty, Array<Type>.Empty, true , true)
#endif
// Task DisposeAsync()
// Availability:
// - MySqlConnector 0.57+
#if NETFRAMEWORK
#if !NATIVE_ASYNC
?? CreateDelegate<Func<IDbConnection, Task>, IDbConnection>(type, "DisposeAsync", Array<Type>.Empty, Array<Type>.Empty, Array<Type>.Empty, false, false);
#else
?? CreateDelegate<Func<IDbConnection, ValueTask>, IDbConnection>(type, "DisposeAsync", Array<Type>.Empty, Array<Type>.Empty, Array<Type>.Empty, false, true);
Expand Down Expand Up @@ -283,7 +281,7 @@ private static async ValueTask<IAsyncDbTransaction> WrapValue<TTransaction>(Valu
//convert a ValueTask result to a Task
body = ToTask(body);
}
#if !NETFRAMEWORK
#if NATIVE_ASYNC
else if (!returnsValueTask && returnValueTask)
{
//convert a Task result to a ValueTask
Expand All @@ -306,7 +304,7 @@ private static MethodCallExpression ToTask(Expression body)
return Expression.Call(body, "AsTask", Array<Type>.Empty);
}

#if !NETFRAMEWORK
#if NATIVE_ASYNC
/// <summary>
/// Returns an expression which returns a <see cref="ValueTask"/> from a <see cref="Task"/>.
/// </summary>
Expand Down Expand Up @@ -373,7 +371,7 @@ private static NewExpression ToValueTTask(Expression body)
//convert a ValueTask result to a Task
body = ToTask(body);
}
#if !NETFRAMEWORK
#if NATIVE_ASYNC
else if (!returnsValueTask && returnValueTask)
{
//convert a Task result to a ValueTask
Expand Down
17 changes: 3 additions & 14 deletions Source/LinqToDB/Async/IAsyncDbConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,14 @@ namespace LinqToDB.Async
/// Asynchronous version of the <see cref="IDbConnection"/> interface, allowing asynchronous operations, missing from <see cref="IDbConnection"/>.
/// </summary>
[PublicAPI]
public interface IAsyncDbConnection : IDbConnection
#if !NETFRAMEWORK
, IAsyncDisposable
#endif
public interface IAsyncDbConnection : IDbConnection, IAsyncDisposable
{
/// <summary>
/// Starts new transaction asynchronously for current connection with default isolation level.
/// </summary>
/// <param name="cancellationToken">Asynchronous operation cancellation token.</param>
/// <returns>Database transaction object.</returns>
#if !NETFRAMEWORK
#if NATIVE_ASYNC
ValueTask<IAsyncDbTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default);
#else
Task<IAsyncDbTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default);
Expand All @@ -33,7 +30,7 @@ public interface IAsyncDbConnection : IDbConnection
/// <param name="isolationLevel">Transaction isolation level.</param>
/// <param name="cancellationToken">Asynchronous operation cancellation token.</param>
/// <returns>Database transaction object.</returns>
#if !NETFRAMEWORK
#if NATIVE_ASYNC
ValueTask<IAsyncDbTransaction> BeginTransactionAsync(IsolationLevel isolationLevel, CancellationToken cancellationToken = default);
#else
Task<IAsyncDbTransaction> BeginTransactionAsync(IsolationLevel isolationLevel, CancellationToken cancellationToken = default);
Expand All @@ -52,14 +49,6 @@ public interface IAsyncDbConnection : IDbConnection
/// <returns>Async operation task.</returns>
Task OpenAsync(CancellationToken cancellationToken = default);

#if NETFRAMEWORK
/// <summary>
/// Disposes current connection asynchonously.
/// </summary>
/// <returns>Async operation task.</returns>
Task DisposeAsync();
#endif

/// <summary>
/// Gets underlying connection instance.
/// </summary>
Expand Down
13 changes: 1 addition & 12 deletions Source/LinqToDB/Async/IAsyncDbTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ namespace LinqToDB.Async
/// Asynchronous version of the <see cref="IDbTransaction"/> interface, allowing asynchronous operations, missing from <see cref="IDbTransaction"/>.
/// </summary>
[PublicAPI]
public interface IAsyncDbTransaction : IDbTransaction
#if !NETFRAMEWORK
, IAsyncDisposable
#endif
public interface IAsyncDbTransaction : IDbTransaction, IAsyncDisposable
{
/// <summary>
/// Commits transaction asynchronously.
Expand All @@ -34,13 +31,5 @@ public interface IAsyncDbTransaction : IDbTransaction
/// Gets underlying transaction instance.
/// </summary>
IDbTransaction Transaction { get; }

#if NETFRAMEWORK
/// <summary>
/// Disposes transaction asynchronously.
/// </summary>
/// <returns>Asynchronous operation completion task.</returns>
Task DisposeAsync();
#endif
}
}
Loading

0 comments on commit 8246efe

Please sign in to comment.