Skip to content

Commit

Permalink
Refactored ODataTable class to simplify adding batch support.
Browse files Browse the repository at this point in the history
  • Loading branch information
object committed Aug 25, 2012
1 parent d44b485 commit 0df83f8
Show file tree
Hide file tree
Showing 13 changed files with 584 additions and 433 deletions.
2 changes: 2 additions & 0 deletions AutoTest.config
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<mm-GraphProvider>BUILTINDARK</mm-GraphProvider>
<StartPaused>true</StartPaused>
<BuildExecutable>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</BuildExecutable> <BuildExecutable>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</BuildExecutable>
</configuration> </configuration>
78 changes: 78 additions & 0 deletions Simple.Data.OData/BatchRequestBuilder.cs
@@ -0,0 +1,78 @@
using System;
using System.Net;
using System.Text;
using Simple.NExtLib;
using Simple.OData;

namespace Simple.Data.OData
{
public class BatchRequestBuilder : RequestBuilder
{
private string _batchId;
private string _changesetId;
private StringBuilder _contentBuilder;

public BatchRequestBuilder(string urlBase)
: base(urlBase)
{
}

public void BeginBatch(string command, string method, string content = null)
{
var uri = CreateRequestUrl(command);
this.Request = (HttpWebRequest)WebRequest.Create(uri);
this.Request.Method = RestVerbs.POST;
_batchId = Guid.NewGuid().ToString();
this.Request.ContentType = "multipart/mixed; boundary=" + _batchId;
_contentBuilder = new StringBuilder();
}

public void EndBatch()
{
_contentBuilder.AppendLine(string.Format("--batch({0})--", _batchId));
AddContent(this.Request, _contentBuilder.ToString());
}

public override void AddTableCommand(string command, string method, string content = null)
{
_contentBuilder.AppendLine(string.Format("--batch_{0}", _batchId));
if (method == RestVerbs.GET)
{
if (_changesetId != null)
{
_contentBuilder.AppendLine(string.Format("--changeset_{0}--", _changesetId));
_contentBuilder.AppendLine();
}
_changesetId = null;
}
else
{
if (_changesetId == null)
{
_changesetId = Guid.NewGuid().ToString();
_contentBuilder.AppendLine(string.Format("Content-Type: multipart/mixed; boundary=changeset_{0}", _changesetId));
_contentBuilder.AppendLine(string.Format("Content-Length: {0}", 0));
_contentBuilder.AppendLine();
_contentBuilder.AppendLine(string.Format("--changeset_{0}", _changesetId));
}
}
_contentBuilder.AppendLine("Content-Type: application/http");
_contentBuilder.AppendLine("Content-Transfer-Encoding:binary");
_contentBuilder.AppendLine();
_contentBuilder.AppendLine(string.Format("{0} {1} HTTP/{2}", method, command, "1.1"));
_contentBuilder.AppendLine(this.Host);

if (content != null)
{
_contentBuilder.AppendLine(string.Format("Content-Type: application/atom+xml;type=entry"));
_contentBuilder.AppendLine(string.Format("Content-Length: {0}", (content ?? string.Empty).Length));
_contentBuilder.Append(content);
}
}

protected override void AddContent(WebRequest request, string content)
{
_contentBuilder.AppendLine(content);
}
}
}
46 changes: 46 additions & 0 deletions Simple.Data.OData/CommandRequestBuilder.cs
@@ -0,0 +1,46 @@
using System.Net;
using Simple.NExtLib;
using Simple.OData;

namespace Simple.Data.OData
{
public class CommandRequestBuilder : RequestBuilder
{
public CommandRequestBuilder(string urlBase)
: base(urlBase)
{
}

public override void AddTableCommand(string command, string method, string content = null)
{
this.Request = CreateTableRequest(command, method, content);
}

protected override void AddContent(WebRequest request, string content)
{
request.ContentType = "application/atom+xml";
request.SetContent(content);
}

private HttpWebRequest CreateTableRequest(string command, string method, string content = null)
{
var uri = CreateRequestUrl(command);
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = method;
request.ContentLength = (content ?? string.Empty).Length;

// TODO: revise
//if (method == "PUT" || method == "DELETE" || method == "MERGE")
//{
// request.Headers.Add("If-Match", "*");
//}

if (content != null)
{
AddContent(request, content);
}

return request;
}
}
}
8 changes: 8 additions & 0 deletions Simple.Data.OData/CommandRequestRunner.cs
@@ -0,0 +1,8 @@
using Simple.OData;

namespace Simple.Data.OData
{
public class CommandRequestRunner : RequestRunner
{
}
}
112 changes: 68 additions & 44 deletions Simple.Data.OData/ODataAdapterTransaction.cs
Expand Up @@ -2,18 +2,32 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Simple.OData;


namespace Simple.Data.OData namespace Simple.Data.OData
{ {
class ODataAdapterTransaction : IAdapterTransaction class ODataAdapterTransaction : IAdapterTransaction
{ {
class AdapterRequest
{
public string MethodName { get; private set; }
public object[] Parameters { get; private set; }

public AdapterRequest(string methodName, params object[] parameters)
{
this.MethodName = methodName;
this.Parameters = parameters;
}
}

private readonly ODataTableAdapter _adapter; private readonly ODataTableAdapter _adapter;
private List<Tuple<string, object[]>> _calls; private List<AdapterRequest> _requests;


public ODataAdapterTransaction(ODataTableAdapter adapter) public ODataAdapterTransaction(ODataTableAdapter adapter)
{ {
_adapter = adapter; _adapter = adapter;
_calls = new List<Tuple<string, object[]>>(); _adapter.SetRequestHandlers(new BatchRequestBuilder(_adapter.UrlBase), new RequestRunner());
_requests = new List<AdapterRequest>();
} }


public string Name public string Name
Expand All @@ -23,54 +37,25 @@ public string Name


public void Commit() public void Commit()
{ {
foreach (var call in _calls) SendBatchRequest();
{ _adapter.SetRequestHandlers(new CommandRequestBuilder(_adapter.UrlBase), new RequestRunner());
switch (call.Item1) _requests.Clear();
{
case "Delete":
_adapter.Delete((string)call.Item2[0], (SimpleExpression)call.Item2[1]);
break;
case "Insert":
_adapter.Insert((string)call.Item2[0], (IDictionary<string, object>)call.Item2[1], (bool)call.Item2[2]);
break;
case "InsertMany":
_adapter.InsertMany((string)call.Item2[0], (IEnumerable<IDictionary<string, object>>)call.Item2[1], (Func<IDictionary<string, object>, Exception, bool>)call.Item2[2], (bool)call.Item2[3]);
break;
case "Update":
_adapter.Update((string)call.Item2[0], (IDictionary<string, object>)call.Item2[1], (SimpleExpression)call.Item2[2]);
break;
case "UpdateMany":
switch (call.Item2.Length)
{
case 2:
_adapter.UpdateMany((string)call.Item2[0], (IEnumerable<IDictionary<string, object>>)call.Item2[1]);
break;
case 3:
if (call.Item2[1] is IList<IDictionary<string, object>>)
_adapter.UpdateMany((string)call.Item2[0], (IList<IDictionary<string, object>>)call.Item2[1], (IEnumerable<string>)call.Item2[2]);
else
_adapter.UpdateMany((string)call.Item2[0], (IEnumerable<IDictionary<string, object>>)call.Item2[1], (IList<string>)call.Item2[2]);
break;
}
break;
}
}
_calls.Clear();
} }


public void Rollback() public void Rollback()
{ {
_calls.Clear(); _adapter.SetRequestHandlers(new CommandRequestBuilder(_adapter.UrlBase), new RequestRunner());
_requests.Clear();
} }


public void Dispose() public void Dispose()
{ {
_calls.Clear(); _requests.Clear();
} }


public int Delete(string tableName, SimpleExpression criteria) public int Delete(string tableName, SimpleExpression criteria)
{ {
_calls.Add(new Tuple<string, object[]>("Delete", new object[] { tableName, criteria })); _requests.Add(new AdapterRequest("Delete", tableName, criteria ));
return 0; return 0;
} }


Expand All @@ -86,13 +71,13 @@ public int Delete(string tableName, SimpleExpression criteria)


public IDictionary<string, object> Insert(string tableName, IDictionary<string, object> data, bool resultRequired) public IDictionary<string, object> Insert(string tableName, IDictionary<string, object> data, bool resultRequired)
{ {
_calls.Add(new Tuple<string, object[]>("Insert", new object[] { tableName, data, resultRequired })); _requests.Add(new AdapterRequest("Insert", tableName, data, resultRequired ));
return null; return null;
} }


public IEnumerable<IDictionary<string, object>> InsertMany(string tableName, IEnumerable<IDictionary<string, object>> data, Func<IDictionary<string, object>, Exception, bool> onError, bool resultRequired) public IEnumerable<IDictionary<string, object>> InsertMany(string tableName, IEnumerable<IDictionary<string, object>> data, Func<IDictionary<string, object>, Exception, bool> onError, bool resultRequired)
{ {
_calls.Add(new Tuple<string, object[]>("InsertMany", new object[] { tableName, data, onError, resultRequired })); _requests.Add(new AdapterRequest("InsertMany", tableName, data, onError, resultRequired ));
return null; return null;
} }


Expand All @@ -103,26 +88,65 @@ public int Delete(string tableName, SimpleExpression criteria)


public int Update(string tableName, IDictionary<string, object> data, SimpleExpression criteria) public int Update(string tableName, IDictionary<string, object> data, SimpleExpression criteria)
{ {
_calls.Add(new Tuple<string, object[]>("Update", new object[] { tableName, data, criteria })); _requests.Add(new AdapterRequest("Update", tableName, data, criteria ));
return 0; return 0;
} }


public int UpdateMany(string tableName, IList<IDictionary<string, object>> dataList, IEnumerable<string> criteriaFieldNames) public int UpdateMany(string tableName, IList<IDictionary<string, object>> dataList, IEnumerable<string> criteriaFieldNames)
{ {
_calls.Add(new Tuple<string, object[]>("UpdateMany", new object[] { tableName, dataList, criteriaFieldNames })); _requests.Add(new AdapterRequest("UpdateMany1", tableName, dataList, criteriaFieldNames ));
return 0; return 0;
} }


public int UpdateMany(string tableName, IEnumerable<IDictionary<string, object>> dataList, IList<string> keyFields) public int UpdateMany(string tableName, IEnumerable<IDictionary<string, object>> dataList, IList<string> keyFields)
{ {
_calls.Add(new Tuple<string, object[]>("UpdateMany", new object[] { tableName, dataList, keyFields })); _requests.Add(new AdapterRequest("UpdateMany2", tableName, dataList, keyFields ));
return 0; return 0;
} }


public int UpdateMany(string tableName, IEnumerable<IDictionary<string, object>> dataList) public int UpdateMany(string tableName, IEnumerable<IDictionary<string, object>> dataList)
{ {
_calls.Add(new Tuple<string, object[]>("UpdateMany", new object[] { tableName, dataList })); _requests.Add(new AdapterRequest("UpdateMany3", tableName, dataList ));
return 0; return 0;
} }

private void SendBatchRequest()
{
foreach (var request in _requests)
{
var tableName = (string)request.Parameters[0];
switch (request.MethodName)
{
case "Delete":
_adapter.Delete(tableName,
(SimpleExpression)request.Parameters[1]);
break;
case "Insert":
_adapter.Insert(tableName,
(IDictionary<string, object>)request.Parameters[1], (bool)request.Parameters[2]);
break;
case "InsertMany":
_adapter.InsertMany(tableName,
(IEnumerable<IDictionary<string, object>>)request.Parameters[1], (Func<IDictionary<string, object>, Exception, bool>)request.Parameters[2], (bool)request.Parameters[3]);
break;
case "Update":
_adapter.Update(tableName,
(IDictionary<string, object>)request.Parameters[1], (SimpleExpression)request.Parameters[2]);
break;
case "UpdateMany1":
_adapter.UpdateMany(tableName,
(IList<IDictionary<string, object>>)request.Parameters[1], (IEnumerable<string>)request.Parameters[2]);
break;
case "UpdateMany2":
_adapter.UpdateMany(tableName,
(IEnumerable<IDictionary<string, object>>)request.Parameters[1], (IList<string>)request.Parameters[2]);
break;
case "UpdateMany3":
_adapter.UpdateMany(tableName,
(IEnumerable<IDictionary<string, object>>)request.Parameters[1]);
break;
}
}
}
} }
} }

0 comments on commit 0df83f8

Please sign in to comment.