Permalink
Browse files

Refactored to AdoAdapterUpserter

  • Loading branch information...
markrendle committed Feb 16, 2012
1 parent a445dd9 commit 3c124f07e4f98ec102c0bdd9e5189ba81a03335b
Showing with 424 additions and 38 deletions.
  1. +14 −13 Simple.Data.Ado/AdoAdapter.IAdapterWithTransactions.cs
  2. +21 −21 Simple.Data.Ado/AdoAdapter.cs
  3. +133 −0 Simple.Data.Ado/AdoAdapterUpserter.cs
  4. +1 −1 Simple.Data.Ado/BulkUpdater.cs
  5. +1 −0 Simple.Data.Ado/Simple.Data.Ado.csproj
  6. +5 −0 Simple.Data.Mocking/XmlMockAdapter.cs
  7. +32 −0 Simple.Data.SqlTest/FindTests.cs
  8. +27 −3 Simple.Data.SqlTest/GetTests.cs
  9. +42 −0 Simple.Data.SqlTest/UpsertTests.cs
  10. +5 −0 Simple.Data.UnitTest/AdapterFactoryTest.cs
  11. +7 −0 Simple.Data/Adapter.cs
  12. +5 −0 Simple.Data/Commands/AllCommand.cs
  13. +5 −0 Simple.Data/Commands/DeleteAllCommand.cs
  14. +5 −0 Simple.Data/Commands/DeleteByCommand.cs
  15. +5 −0 Simple.Data/Commands/ExistsByCommand.cs
  16. +5 −0 Simple.Data/Commands/ExistsCommand.cs
  17. +5 −0 Simple.Data/Commands/FindAllByCommand.cs
  18. +5 −0 Simple.Data/Commands/FindAllCommand.cs
  19. +9 −0 Simple.Data/Commands/FindByCommand.cs
  20. +5 −0 Simple.Data/Commands/FindCommand.cs
  21. +10 −0 Simple.Data/Commands/GetCommand.cs
  22. +5 −0 Simple.Data/Commands/GetCountByCommand.cs
  23. +5 −0 Simple.Data/Commands/GetCountCommand.cs
  24. +2 −0 Simple.Data/Commands/ICommand.cs
  25. +5 −0 Simple.Data/Commands/InsertCommand.cs
  26. +10 −0 Simple.Data/Commands/QueryByCommand.cs
  27. +5 −0 Simple.Data/Commands/UpdateAllCommand.cs
  28. +5 −0 Simple.Data/Commands/UpdateByCommand.cs
  29. +5 −0 Simple.Data/Commands/UpdateCommand.cs
  30. +5 −0 Simple.Data/Commands/UpsertByCommand.cs
  31. +5 −0 Simple.Data/Commands/UpsertCommand.cs
  32. +6 −0 Simple.Data/DynamicTable.cs
  33. +6 −0 Simple.Data/InMemoryAdapter.cs
  34. +13 −0 Simple.Data/SimpleQuery.cs
@@ -57,7 +57,7 @@ public IAdapterTransaction BeginTransaction(IsolationLevel isolationLevel, strin
public int Update(string tableName, IDictionary<string, object> data, IAdapterTransaction adapterTransaction)
{
- string[] keyFieldNames = GetKeyFieldNames(tableName).ToArray();
+ string[] keyFieldNames = GetKeyNames(tableName).ToArray();
if (keyFieldNames.Length == 0) throw new AdoAdapterException("No Primary Key found for implicit update");
return Update(tableName, data, GetCriteria(tableName, keyFieldNames, data), adapterTransaction);
}
@@ -126,18 +126,19 @@ public int Delete(string tableName, SimpleExpression criteria, IAdapterTransacti
public override IDictionary<string, object> Upsert(string tableName, IDictionary<string, object> data, SimpleExpression criteria, bool resultRequired, IAdapterTransaction adapterTransaction)
{
var transaction = ((AdoAdapterTransaction) adapterTransaction).Transaction;
- var finder = new AdoAdapterFinder(this, transaction);
- if (finder.FindOne(tableName, criteria) != null)
- {
- // Don't update columns used as criteria
- var keys = criteria.GetOperandsOfType<ObjectReference>().Select(o => o.GetName().Homogenize());
- data = data.Where(kvp => keys.All(k => k != kvp.Key.Homogenize())).ToDictionary();
-
- var commandBuilder = new UpdateHelper(_schema).GetUpdateCommand(tableName, data, criteria);
- Execute(commandBuilder, adapterTransaction);
- return resultRequired ? finder.FindOne(tableName, criteria) : null;
- }
- return new AdoAdapterInserter(this, transaction).Insert(tableName, data, resultRequired);
+ return new AdoAdapterUpserter(this, transaction).Upsert(tableName, data, criteria, resultRequired);
+ }
+
+ public override IEnumerable<IDictionary<string, object>> UpsertMany(string tableName, IList<IDictionary<string, object>> list, IAdapterTransaction adapterTransaction, bool isResultRequired, Func<IDictionary<string, object>, Exception, bool> errorCallback)
+ {
+ var transaction = ((AdoAdapterTransaction) adapterTransaction).Transaction;
+ return new AdoAdapterUpserter(this, transaction).UpsertMany(tableName, list, isResultRequired, errorCallback);
+ }
+
+ public override IEnumerable<IDictionary<string, object>> UpsertMany(string tableName, IList<IDictionary<string, object>> list, IEnumerable<string> keyFieldNames, IAdapterTransaction adapterTransaction, bool isResultRequired, Func<IDictionary<string, object>, Exception, bool> errorCallback)
+ {
+ var transaction = ((AdoAdapterTransaction) adapterTransaction).Transaction;
+ return new AdoAdapterUpserter(this, transaction).UpsertMany(tableName, list, keyFieldNames.ToArray(), isResultRequired, errorCallback);
}
}
}
@@ -79,7 +79,7 @@ public ISchemaProvider SchemaProvider
public override IDictionary<string, object> GetKey(string tableName, IDictionary<string, object> record)
{
var homogenizedRecord = new Dictionary<string, object>(record, HomogenizedEqualityComparer.DefaultInstance);
- return GetKeyFieldNames(tableName).ToDictionary(key => key,
+ return GetKeyNames(tableName).ToDictionary(key => key,
key => homogenizedRecord.ContainsKey(key) ? homogenizedRecord[key] : null);
}
@@ -233,9 +233,9 @@ public override int Delete(string tableName, SimpleExpression criteria)
/// </summary>
/// <param name="tableName">Name of the table.</param>
/// <returns>A list of field names; an empty list if no key is defined.</returns>
- public IEnumerable<string> GetKeyFieldNames(string tableName)
+ public override IList<string> GetKeyNames(string tableName)
{
- return _schema.FindTable(tableName).PrimaryKey.AsEnumerable();
+ return _schema.FindTable(tableName).PrimaryKey.AsEnumerable().ToList();
}
private int Execute(ICommandBuilder commandBuilder)
@@ -250,7 +250,8 @@ private int Execute(ICommandBuilder commandBuilder)
}
}
}
- private int Execute(ICommandBuilder commandBuilder, IDbConnection connection)
+
+ internal static int Execute(ICommandBuilder commandBuilder, IDbConnection connection)
{
using (connection.MaybeDisposable())
{
@@ -262,9 +263,14 @@ private int Execute(ICommandBuilder commandBuilder, IDbConnection connection)
}
}
- private static int Execute(ICommandBuilder commandBuilder, IAdapterTransaction transaction)
+ internal static int Execute(ICommandBuilder commandBuilder, IAdapterTransaction transaction)
{
IDbTransaction dbTransaction = ((AdoAdapterTransaction) transaction).Transaction;
+ return Execute(commandBuilder, dbTransaction);
+ }
+
+ internal static int Execute(ICommandBuilder commandBuilder, IDbTransaction dbTransaction)
+ {
using (IDbCommand command = commandBuilder.GetCommand(dbTransaction.Connection))
{
command.Transaction = dbTransaction;
@@ -307,23 +313,17 @@ public DatabaseSchema GetSchema()
public override IDictionary<string, object> Upsert(string tableName, IDictionary<string, object> data, SimpleExpression criteria, bool resultRequired)
{
- var connection = CreateConnection();
- using (connection.MaybeDisposable())
- {
- connection.OpenIfClosed();
- var finder = new AdoAdapterFinder(this, connection);
- if (finder.FindOne(tableName, criteria) != null)
- {
- // Don't update columns used as criteria
- var keys = criteria.GetOperandsOfType<ObjectReference>().Select(o => o.GetName().Homogenize());
- data = data.Where(kvp => keys.All(k => k != kvp.Key.Homogenize())).ToDictionary();
+ return new AdoAdapterUpserter(this).Upsert(tableName, data, criteria, resultRequired);
+ }
- var commandBuilder = new UpdateHelper(_schema).GetUpdateCommand(tableName, data, criteria);
- Execute(commandBuilder, connection);
- return resultRequired ? finder.FindOne(tableName, criteria) : null;
- }
- return new AdoAdapterInserter(this, connection).Insert(tableName, data, resultRequired);
- }
+ public override IEnumerable<IDictionary<string, object>> UpsertMany(string tableName, IList<IDictionary<string, object>> list, bool isResultRequired, Func<IDictionary<string, object>, Exception, bool> errorCallback)
+ {
+ return new AdoAdapterUpserter(this).UpsertMany(tableName, list, isResultRequired, errorCallback);
+ }
+
+ public override IEnumerable<IDictionary<string, object>> UpsertMany(string tableName, IList<IDictionary<string, object>> list, IEnumerable<string> keyFieldNames, bool isResultRequired, Func<IDictionary<string, object>, Exception, bool> errorCallback)
+ {
+ return new AdoAdapterUpserter(this).UpsertMany(tableName, list, keyFieldNames.ToArray(), isResultRequired, errorCallback);
}
public string GetIdentityFunction()
@@ -0,0 +1,133 @@
+namespace Simple.Data.Ado
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Data;
+ using System.Linq;
+ using Extensions;
+
+ class AdoAdapterUpserter
+ {
+ private readonly AdoAdapter _adapter;
+ private readonly IDbConnection _connection;
+ private readonly IDbTransaction _transaction;
+
+ public AdoAdapterUpserter(AdoAdapter adapter) : this(adapter, (IDbTransaction)null)
+ {
+ }
+
+ public AdoAdapterUpserter(AdoAdapter adapter, IDbConnection connection)
+ {
+ _adapter = adapter;
+ _connection = connection;
+ }
+
+ public AdoAdapterUpserter(AdoAdapter adapter, IDbTransaction transaction)
+ {
+ _adapter = adapter;
+ _transaction = transaction;
+ if (transaction != null) _connection = transaction.Connection;
+ }
+
+ public IDictionary<string, object> Upsert(string tableName, IDictionary<string, object> data, SimpleExpression criteria, bool resultRequired)
+ {
+ var connection = _connection ?? _adapter.CreateConnection();
+ using (connection.MaybeDisposable())
+ {
+ connection.OpenIfClosed();
+ return Upsert(tableName, data, criteria, resultRequired, connection);
+ }
+ }
+
+ private IDictionary<string, object> Upsert(string tableName, IDictionary<string, object> data, SimpleExpression criteria, bool resultRequired,
+ IDbConnection connection)
+ {
+ var finder = _transaction == null
+ ? new AdoAdapterFinder(_adapter, connection)
+ : new AdoAdapterFinder(_adapter, _transaction);
+ if (finder.FindOne(tableName, criteria) != null)
+ {
+ // Don't update columns used as criteria
+ var keys = criteria.GetOperandsOfType<ObjectReference>().Select(o => o.GetName().Homogenize());
+ data = data.Where(kvp => keys.All(k => k != kvp.Key.Homogenize())).ToDictionary();
+
+ var commandBuilder = new UpdateHelper(_adapter.GetSchema()).GetUpdateCommand(tableName, data, criteria);
+ if (_transaction == null)
+ {
+ AdoAdapter.Execute(commandBuilder, connection);
+ }
+ else
+ {
+ AdoAdapter.Execute(commandBuilder, _transaction);
+ }
+ return resultRequired ? finder.FindOne(tableName, criteria) : null;
+ }
+ var inserter = _transaction == null
+ ? new AdoAdapterInserter(_adapter, connection)
+ : new AdoAdapterInserter(_adapter, _transaction);
+ return inserter.Insert(tableName, data, resultRequired);
+ }
+
+
+ public IEnumerable<IDictionary<string, object>> UpsertMany(string tableName, IList<IDictionary<string, object>> list, bool isResultRequired, Func<IDictionary<string, object>, Exception, bool> errorCallback)
+ {
+ foreach (var row in list)
+ {
+ IDictionary<string, object> result;
+ try
+ {
+ var criteria = ExpressionHelper.CriteriaDictionaryToExpression(tableName,
+ _adapter.GetKey(tableName, row));
+ result = Upsert(tableName, row, criteria, isResultRequired);
+ }
+ catch (Exception ex)
+ {
+ if (errorCallback(row, ex)) continue;
+ throw;
+ }
+
+ yield return result;
+ }
+ }
+
+ public IEnumerable<IDictionary<string, object>> UpsertMany(string tableName, IList<IDictionary<string, object>> list, IList<string> keyFieldNames, bool isResultRequired, Func<IDictionary<string, object>, Exception, bool> errorCallback)
+ {
+ foreach (var row in list)
+ {
+ IDictionary<string, object> result;
+ try
+ {
+ var criteria = GetCriteria(tableName, keyFieldNames, row);
+ result = Upsert(tableName, row, criteria, isResultRequired);
+ }
+ catch (Exception ex)
+ {
+ if (errorCallback(row, ex)) continue;
+ throw;
+ }
+
+ yield return result;
+ }
+ }
+
+ private static SimpleExpression GetCriteria(string tableName, IEnumerable<string> criteriaFieldNames,
+ IDictionary<string, object> record)
+ {
+ var criteria = new Dictionary<string, object>();
+
+ foreach (var criteriaFieldName in criteriaFieldNames)
+ {
+ var name = criteriaFieldName;
+ var keyValuePair = record.SingleOrDefault(kvp => kvp.Key.Homogenize().Equals(name.Homogenize()));
+ if (string.IsNullOrWhiteSpace(keyValuePair.Key))
+ {
+ throw new InvalidOperationException("Key field value not set.");
+ }
+
+ criteria.Add(criteriaFieldName, keyValuePair.Value);
+ record.Remove(keyValuePair);
+ }
+ return ExpressionHelper.CriteriaDictionaryToExpression(tableName, criteria);
+ }
+ }
+}
@@ -12,7 +12,7 @@ class BulkUpdater : IBulkUpdater
{
public int Update(AdoAdapter adapter, string tableName, IList<IDictionary<string, object>> data, IDbTransaction transaction)
{
- return Update(adapter, tableName, data, adapter.GetKeyFieldNames(tableName).ToList(), transaction);
+ return Update(adapter, tableName, data, adapter.GetKeyNames(tableName).ToList(), transaction);
}
public int Update(AdoAdapter adapter, string tableName, IList<IDictionary<string, object>> data, IEnumerable<string> criteriaFieldNames, IDbTransaction transaction)
@@ -63,6 +63,7 @@
<Compile Include="AdoAdapterQueryRunner.cs" />
<Compile Include="AdoAdapterRelatedFinder.cs" />
<Compile Include="AdoAdapterTransaction.cs" />
+ <Compile Include="AdoAdapterUpserter.cs" />
<Compile Include="BulkInserter.cs" />
<Compile Include="BulkInserterHelper.cs" />
<Compile Include="BulkInserterTransactionHelper.cs" />
@@ -33,6 +33,11 @@ public XElement Data
key => record.ContainsKey(key) ? record[key] : null);
}
+ public override IList<string> GetKeyNames(string tableName)
+ {
+ return GetKeyFieldNames(tableName).ToList();
+ }
+
public override IDictionary<string, object> Get(string tableName, params object[] keyValues)
{
throw new NotImplementedException();
@@ -10,6 +10,8 @@
namespace Simple.Data.SqlTest
{
+ using System;
+
/// <summary>
/// Summary description for FindTests
/// </summary>
@@ -172,5 +174,35 @@ public void FindByWithNamedParameter()
Assert.IsNotNull(user);
}
+
+ [Test]
+ public void WithClauseShouldCastToStaticTypeWithCollection()
+ {
+ var db = DatabaseHelper.Open();
+ Customer actual = db.Customers.WithOrders().FindByCustomerId(1);
+ Assert.IsNotNull(actual);
+ Assert.AreEqual(1, actual.Orders.Single().OrderId);
+ Assert.AreEqual(new DateTime(2010, 10, 10), actual.Orders.Single().OrderDate);
+ }
+
+ [Test]
+ public void NamedParameterAndWithClauseShouldCastToStaticTypeWithCollection()
+ {
+ var db = DatabaseHelper.Open();
+ Customer actual = db.Customers.WithOrders().FindBy(CustomerId: 1);
+ Assert.IsNotNull(actual);
+ Assert.AreEqual(1, actual.Orders.Single().OrderId);
+ Assert.AreEqual(new DateTime(2010, 10, 10), actual.Orders.Single().OrderDate);
+ }
+
+ [Test]
+ public void ExpressionAndWithClauseShouldCastToStaticTypeWithCollection()
+ {
+ var db = DatabaseHelper.Open();
+ Customer actual = db.Customers.WithOrders().Find(db.Customers.CustomerId == 1);
+ Assert.IsNotNull(actual);
+ Assert.AreEqual(1, actual.Orders.Single().OrderId);
+ Assert.AreEqual(new DateTime(2010, 10, 10), actual.Orders.Single().OrderDate);
+ }
}
}
@@ -2,6 +2,9 @@
namespace Simple.Data.SqlTest
{
+ using System;
+ using System.Linq;
+
[TestFixture]
public class GetTests
{
@@ -14,9 +17,30 @@ public void Setup()
[Test]
public void TestGet()
{
-var db = DatabaseHelper.Open();
-var user = db.Users.Get(1);
-Assert.AreEqual(1, user.Id);
+ var db = DatabaseHelper.Open();
+ var user = db.Users.Get(1);
+ Assert.AreEqual(1, user.Id);
+ }
+
+ [Test]
+ public void WithClauseShouldCastToStaticTypeWithComplexProperty()
+ {
+ var db = DatabaseHelper.Open();
+ Order actual = db.Orders.WithCustomer().Get(1);
+ Assert.IsNotNull(actual);
+ Assert.IsNotNull(actual.Customer);
+ Assert.AreEqual("Test", actual.Customer.Name);
+ Assert.AreEqual("100 Road", actual.Customer.Address);
+ }
+
+ [Test]
+ public void WithClauseShouldCastToStaticTypeWithCollection()
+ {
+ var db = DatabaseHelper.Open();
+ Customer actual = db.Customers.WithOrders().Get(1);
+ Assert.IsNotNull(actual);
+ Assert.AreEqual(1, actual.Orders.Single().OrderId);
+ Assert.AreEqual(new DateTime(2010, 10, 10), actual.Orders.Single().OrderDate);
}
}
}
Oops, something went wrong.

0 comments on commit 3c124f0

Please sign in to comment.