Skip to content

Commit

Permalink
Merge pull request PostgreSQLCopyHelper#45 from PostgreSQLCopyHelper/…
Browse files Browse the repository at this point in the history
…Start-Of-Async

Async Support
  • Loading branch information
bytefish authored Aug 27, 2019
2 parents 7c67a80 + 394de7e commit 7b32f82
Show file tree
Hide file tree
Showing 27 changed files with 110 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Collections.Generic;
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Generic;
using Npgsql;

namespace PostgreSQLCopyHelper.Test.Extensions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using Npgsql;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using Npgsql;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.14.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.15.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Npgsql;
using NUnit.Framework;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using NpgsqlTypes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using NpgsqlTypes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using NpgsqlTypes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using NpgsqlTypes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using NpgsqlTypes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using NpgsqlTypes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using NpgsqlTypes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using NpgsqlTypes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Net;
Expand All @@ -20,4 +19,4 @@ public static PostgreSQLCopyHelper<TEntity> MapMacAddress<TEntity>(this PostgreS
return helper.Map(columnName, propertyGetter, NpgsqlDbType.MacAddr);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using NpgsqlTypes;
Expand Down Expand Up @@ -68,4 +67,4 @@ public static PostgreSQLCopyHelper<TEntity> MapDouble<TEntity>(this PostgreSQLCo
return helper.MapNullable(columnName, propertyGetter, NpgsqlDbType.Double);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using NpgsqlTypes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Npgsql;

namespace PostgreSQLCopyHelper
{
public interface IPostgreSQLCopyHelper<TEntity>
{
ulong SaveAll(NpgsqlConnection connection, IEnumerable<TEntity> entities);
ValueTask<ulong> SaveAllAsync(NpgsqlConnection connection, IEnumerable<TEntity> entities, CancellationToken cancellationToken = default);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Threading.Tasks;
using Npgsql;

namespace PostgreSQLCopyHelper.Model
Expand All @@ -10,7 +10,7 @@ internal class ColumnDefinition<TEntity>
{
public string ColumnName { get; set; }

public Action<NpgsqlBinaryImporter, TEntity> Write { get; set; }
public Func<NpgsqlBinaryImporter, TEntity, Task> Write { get; set; }

public override string ToString()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using PostgreSQLCopyHelper.Utils;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Npgsql;
using NpgsqlTypes;
using PostgreSQLCopyHelper.Model;
Expand Down Expand Up @@ -37,13 +38,29 @@ public PostgreSQLCopyHelper(string schemaName, string tableName)
_columns = new List<ColumnDefinition<TEntity>>();
}

public ulong SaveAll(NpgsqlConnection connection, IEnumerable<TEntity> entities)
public ulong SaveAll(NpgsqlConnection connection, IEnumerable<TEntity> entities) =>
DoSaveAllAsync(connection, entities).GetAwaiter().GetResult();

public ValueTask<ulong> SaveAllAsync(NpgsqlConnection connection, IEnumerable<TEntity> entities, CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
return new ValueTask<ulong>(Task.FromCanceled<ulong>(cancellationToken));
}

using (NoSynchronizationContextScope.Enter())
{
return DoSaveAllAsync(connection, entities);
}
}

private async ValueTask<ulong> DoSaveAllAsync(NpgsqlConnection connection, IEnumerable<TEntity> entities)
{
using (var binaryCopyWriter = connection.BeginBinaryImport(GetCopyCommand()))
{
WriteToStream(binaryCopyWriter, entities);
await WriteToStream(binaryCopyWriter, entities);

return binaryCopyWriter.Complete();
return await binaryCopyWriter.CompleteAsync();
}
}

Expand All @@ -56,41 +73,41 @@ public PostgreSQLCopyHelper<TEntity> UsePostgresQuoting(bool enabled = true)

public PostgreSQLCopyHelper<TEntity> Map<TProperty>(string columnName, Func<TEntity, TProperty> propertyGetter, NpgsqlDbType type)
{
return AddColumn(columnName, (writer, entity) => writer.Write(propertyGetter(entity), type));
return AddColumn(columnName, (writer, entity) => writer.WriteAsync(propertyGetter(entity), type));
}

public PostgreSQLCopyHelper<TEntity> MapNullable<TProperty>(string columnName, Func<TEntity, TProperty?> propertyGetter, NpgsqlDbType type)
where TProperty : struct
{
return AddColumn(columnName, (writer, entity) =>
return AddColumn(columnName, async (writer, entity) =>
{
var val = propertyGetter(entity);

if (!val.HasValue)
{
writer.WriteNull();
await writer.WriteNullAsync();
}
else
{
writer.Write(val.Value, type);
await writer.WriteAsync(val.Value, type);
}
});
}

private void WriteToStream(NpgsqlBinaryImporter writer, IEnumerable<TEntity> entities)
private async Task WriteToStream(NpgsqlBinaryImporter writer, IEnumerable<TEntity> entities)
{
foreach (var entity in entities)
{
writer.StartRow();
await writer.StartRowAsync();

foreach (var columnDefinition in _columns)
{
columnDefinition.Write(writer, entity);
await columnDefinition.Write(writer, entity);
}
}
}

private PostgreSQLCopyHelper<TEntity> AddColumn(string columnName, Action<NpgsqlBinaryImporter, TEntity> action)
private PostgreSQLCopyHelper<TEntity> AddColumn(string columnName, Func<NpgsqlBinaryImporter, TEntity, Task> action)
{
_columns.Add(new ColumnDefinition<TEntity>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Npgsql" Version="4.1.0-preview1" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-19367-01">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql" Version="4.1.0-ci.2184" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Code taken from https://github.com/npgsql/npgsql/blob/dev/src/Npgsql/NoSynchronizationContextScope.cs

using System;
using System.Threading;

namespace PostgreSQLCopyHelper.Utils
{
/// <summary>
/// This mechanism is used to temporarily set the current synchronization context to null while
/// executing Npgsql code, making all await continuations execute on the thread pool. This replaces
/// the need to place ConfigureAwait(false) everywhere, and should be used in all surface async methods,
/// without exception.
///
/// Warning: do not use this directly in async methods, use it in sync wrappers of async methods
/// (see https://github.com/npgsql/npgsql/issues/1593)
/// </summary>
/// <remarks>
/// http://stackoverflow.com/a/28307965/640325
/// </remarks>
internal static class NoSynchronizationContextScope
{
internal static Disposable Enter()
{
var sc = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
return new Disposable(sc);
}

internal struct Disposable : IDisposable
{
private readonly SynchronizationContext _synchronizationContext;

internal Disposable(SynchronizationContext synchronizationContext)
=> _synchronizationContext = synchronizationContext;

public void Dispose()
=> SynchronizationContext.SetSynchronizationContext(_synchronizationContext);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Linq;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace PostgreSQLCopyHelper.Utils
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace PostgreSQLCopyHelper.Utils
{
public static class StringExtensions
{
Expand Down

0 comments on commit 7b32f82

Please sign in to comment.