Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Thread-Safe SqlGenerator implementation #309

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 1 addition & 48 deletions DapperExtensions.StrongName/DapperExtensions.StrongName.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -94,53 +94,6 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\DapperExtensions\DapperAsyncExtensions.cs" Link="DapperAsyncExtensions.cs" />
<Compile Include="..\DapperExtensions\DapperAsyncImplementor.cs" Link="DapperAsyncImplementor.cs" />
<Compile Include="..\DapperExtensions\DapperExtensions.cs" Link="DapperExtensions.cs" />
<Compile Include="..\DapperExtensions\DapperExtensionsConfiguration.cs" Link="DapperExtensionsConfiguration.cs" />
<Compile Include="..\DapperExtensions\DapperImplementor.cs" Link="DapperImplementor.cs" />
<Compile Include="..\DapperExtensions\Database.cs" Link="Database.cs" />
<Compile Include="..\DapperExtensions\GetMultipleResult.cs" Link="GetMultipleResult.cs" />
<Compile Include="..\DapperExtensions\Predicates.cs" Link="Predicates.cs" />
<Compile Include="..\DapperExtensions\ReflectionHelper.cs" Link="ReflectionHelper.cs" />
<Compile Include="..\DapperExtensions\Enums\Comparator.cs" Link="Enums\Comparator.cs" />
<Compile Include="..\DapperExtensions\Extensions\EnumExtensions.cs" Link="Extensions\EnumExtensions.cs" />

<Compile Include="..\DapperExtensions\Mapper\AutoClassMapper.cs" Link="Mapper\AutoClassMapper.cs" />
<Compile Include="..\DapperExtensions\Mapper\ClassMapper.cs" Link="Mapper\ClassMapper.cs" />
<Compile Include="..\DapperExtensions\Mapper\Column.cs" Link="Mapper\Column.cs" />
<Compile Include="..\DapperExtensions\Mapper\MemberMap.cs" Link="Mapper\MemberMap.cs" />
<Compile Include="..\DapperExtensions\Mapper\Parameter.cs" Link="Mapper\Parameter.cs" />
<Compile Include="..\DapperExtensions\Mapper\PluralizedAutoClassMapper.cs" Link="Mapper\PluralizedAutoClassMapper.cs" />
<Compile Include="..\DapperExtensions\Mapper\PropertyKey.cs" Link="Mapper\PropertyKey.cs" />
<Compile Include="..\DapperExtensions\Mapper\ReferenceMap.cs" Link="Mapper\ReferenceMap.cs" />
<Compile Include="..\DapperExtensions\Mapper\ReferenceProperty.cs" Link="Mapper\ReferenceProperty.cs" />
<Compile Include="..\DapperExtensions\Mapper\Table.cs" Link="Mapper\Table.cs" />

<Compile Include="..\DapperExtensions\Predicate\BasePredicate.cs" Link="Predicate\BasePredicate.cs" />
<Compile Include="..\DapperExtensions\Predicate\BetweenPredicate.cs" Link="Predicate\BetweenPredicate.cs" />
<Compile Include="..\DapperExtensions\Predicate\ComparePredicate.cs" Link="Predicate\ComparePredicate.cs" />
<Compile Include="..\DapperExtensions\Predicate\ExistsPredicate.cs" Link="Predicate\ExistsPredicate.cs" />
<Compile Include="..\DapperExtensions\Predicate\FieldPredicate.cs" Link="Predicate\FieldPredicate.cs" />
<Compile Include="..\DapperExtensions\Predicate\GetMultiplePredicate.cs" Link="Predicate\GetMultiplePredicate.cs" />
<Compile Include="..\DapperExtensions\Predicate\InPredicate.cs" Link="Predicate\InPredicate.cs" />
<Compile Include="..\DapperExtensions\Predicate\IPredicate.cs" Link="Predicate\IPredicate.cs" />
<Compile Include="..\DapperExtensions\Predicate\PredicateEnums.cs" Link="Predicate\PredicateEnums.cs" />
<Compile Include="..\DapperExtensions\Predicate\PredicateGroup.cs" Link="Predicate\PredicateGroup.cs" />
<Compile Include="..\DapperExtensions\Predicate\Projection.cs" Link="Predicate\Projection.cs" />
<Compile Include="..\DapperExtensions\Predicate\PropertyPredicate.cs" Link="Predicate\PropertyPredicate.cs" />
<Compile Include="..\DapperExtensions\Predicate\Sort.cs" Link="Predicate\Sort.cs" />
<Compile Include="..\DapperExtensions\Predicate\VirtualPredicate.cs" Link="Predicate\VirtualPredicate.cs" />

<Compile Include="..\DapperExtensions\Sql\DB2Dialect.cs" Link="Sql\DB2Dialect.cs" />
<Compile Include="..\DapperExtensions\Sql\MySqlDialect.cs" Link="Sql\MySqlDialect.cs" />
<Compile Include="..\DapperExtensions\Sql\OracleDialect.cs" Link="Sql\OracleDialect.cs" />
<Compile Include="..\DapperExtensions\Sql\PostgreSqlDialect.cs" Link="Sql\PostgreSqlDialect.cs" />
<Compile Include="..\DapperExtensions\Sql\SqlCeDialect.cs" Link="Sql\SqlCeDialect.cs" />
<Compile Include="..\DapperExtensions\Sql\SqlDialectBase.cs" Link="Sql\SqlDialectBase.cs" />
<Compile Include="..\DapperExtensions\Sql\SqlGenerator.cs" Link="Sql\SqlGenerator.cs" />
<Compile Include="..\DapperExtensions\Sql\SqlInjection.cs" Link="Sql\SqlInjection.cs" />
<Compile Include="..\DapperExtensions\Sql\SqliteDialect.cs" Link="Sql\SqliteDialect.cs" />
<Compile Include="..\DapperExtensions\Sql\SqlServerDialect.cs" Link="Sql\SqlServerDialect.cs" />
<Compile Include="..\DapperExtensions\**\*.cs" Exclude="..\DapperExtensions\obj\**\*.cs" LinkBase="." />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ protected DatabaseAsyncTestsFixture(string configPath = null) : base(configPath)
protected override void CommonSetup(DbConnection connection, SqlDialectBase sqlDialect)
{
var config = DapperAsyncExtensions.Configure(typeof(AutoClassMapper<>), new List<Assembly>(), sqlDialect);
var sqlGenerator = new SqlGeneratorImpl(config);
var sqlGenerator = new ThreadSafeSqlGeneratorImpl(config);
Db = new AsyncDatabase(connection, sqlGenerator);
}

Expand Down
34 changes: 34 additions & 0 deletions DapperExtensions.Test/IntegrationTests/Async/Sqlite/CrudFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,40 @@ public void UsingCompositeKey_UpdatesEntity()
Assert.AreEqual("key", m3.Key2);
Assert.AreEqual("barz", m3.Value);
}

[Test]
public async Task AsyncBatch_UsingKey_UpdatesEntity()
{
Person p1 = new Person
{
Active = true,
FirstName = "Foo",
LastName = "Bar",
DateCreated = DateTime.UtcNow
};
var animal = new Animal
{
Name = "Fizz"
};
p1.Id = await Db.Insert(p1);
animal.Id = await Db.Insert(animal);

p1.FirstName = "Baz";
p1.Active = false;

animal.Name = "Buzz";

var task1 = Task.Run(() => Db.Update(p1, ignoreAllKeyProperties: true));
var task2 = Task.Run(() => Db.Update(animal, ignoreAllKeyProperties: true));
await Task.WhenAll(task1, task2);

var p1_3 = await Db.Get<Person>(p1.Id);
Assert.AreEqual("Baz", p1_3.FirstName);
Assert.AreEqual("Bar", p1_3.LastName);
Assert.AreEqual(false, p1_3.Active);
var a2 = await Db.Get<Animal>(animal.Id);
Assert.AreEqual("Buzz", a2.Name);
}
}

[TestFixture]
Expand Down
2 changes: 1 addition & 1 deletion DapperExtensions/DapperAsyncExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public static Func<IDapperExtensionsConfiguration, IDapperAsyncImplementor> Inst
{
get
{
return _instanceFactory ??= config => new DapperAsyncImplementor(new SqlGeneratorImpl(_configuration));
return _instanceFactory ??= config => new DapperAsyncImplementor(new ThreadSafeSqlGeneratorImpl(_configuration));
}
set
{
Expand Down
2 changes: 1 addition & 1 deletion DapperExtensions/DapperExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public static Func<IDapperExtensionsConfiguration, IDapperImplementor> InstanceF
{
get
{
return _instanceFactory ??= config => new DapperImplementor(new SqlGeneratorImpl(config));
return _instanceFactory ??= config => new DapperImplementor(new ThreadSafeSqlGeneratorImpl(config));
}
set
{
Expand Down
110 changes: 110 additions & 0 deletions DapperExtensions/Sql/ThreadSafeSqlGeneratorImpl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.Threading;
using DapperExtensions.Mapper;
using DapperExtensions.Predicate;

namespace DapperExtensions.Sql
{
public class ThreadSafeSqlGeneratorImpl : ISqlGenerator
{

[ThreadStatic]
private static SqlGeneratorImpl _sqlGeneratorImpl;

private SqlGeneratorImpl Current => LazyInitializer.EnsureInitialized(ref _sqlGeneratorImpl, () => new SqlGeneratorImpl(Configuration));

public ThreadSafeSqlGeneratorImpl(IDapperExtensionsConfiguration configuration)
{
this.Configuration = configuration;
}

public IDapperExtensionsConfiguration Configuration { get; }

public IList<IColumn> AllColumns => Current.AllColumns;

public IList<Table> MappedTables => Current.MappedTables;

public bool SupportsMultipleStatements()
{
return this.Configuration.Dialect.SupportsMultipleStatements;
}


public string Select(IClassMapper classMap, IPredicate predicate, IList<ISort> sort,
IDictionary<string, object> parameters, IList<IProjection> colsToSelect,
IList<IReferenceMap> includedProperties = null)
{
return this.Current.Select(classMap, predicate, sort, parameters, colsToSelect, includedProperties);
}

public string SelectPaged(IClassMapper classMap, IPredicate predicate, IList<ISort> sort, int page,
int resultsPerPage,
IDictionary<string, object> parameters, IList<IProjection> colsToSelect,
IList<IReferenceMap> includedProperties = null)
{
return this.Current.SelectPaged(classMap, predicate, sort, page, resultsPerPage, parameters,
colsToSelect, includedProperties);

}

public string SelectSet(IClassMapper classMap, IPredicate predicate, IList<ISort> sort, int firstResult,
int maxResults,
IDictionary<string, object> parameters, IList<IProjection> colsToSelect,
IList<IReferenceMap> includedProperties = null)
{
return this.Current.SelectSet(classMap, predicate, sort, firstResult, maxResults, parameters,
colsToSelect, includedProperties);

}

public string Count(IClassMapper classMap, IPredicate predicate, IDictionary<string, object> parameters,
IList<IReferenceMap> includedProperties = null)
{
return this.Current.Count(classMap, predicate, parameters, includedProperties);
}

public string Insert(IClassMapper classMap)
{
return this.Current.Insert(classMap);
}

public string Update(IClassMapper classMap, IPredicate predicate, IDictionary<string, object> parameters,
bool ignoreAllKeyProperties,
IList<IProjection> colsToUpdate)
{
return this.Current.Update(classMap, predicate, parameters, ignoreAllKeyProperties, colsToUpdate);
}

public string Delete(IClassMapper classMap, IPredicate predicate, IDictionary<string, object> parameters)
{
return this.Current.Delete(classMap, predicate, parameters);
}

public string IdentitySql(IClassMapper classMap)
{
return this.Current.IdentitySql(classMap);
}

public string GetTableName(IClassMapper map, bool useAlias = false)
{
return this.Current.GetTableName(map, useAlias);
}

public string GetColumnName(IClassMapper map, IMemberMap property, bool includeAlias, bool isDml = false,
bool includePrefix = true)
{
return this.Current.GetColumnName(map, property, includeAlias, isDml, includePrefix);
}

public string GetColumnName(IClassMapper map, string propertyName, bool includeAlias, bool includePrefix = true)
{
return this.Current.GetColumnName(map, propertyName, includeAlias, includePrefix);
}

public string GetColumnName(IColumn column, bool includeAlias, bool includePrefix = true)
{
return this.Current.GetColumnName(column, includeAlias, includePrefix);
}
}
}