Skip to content

Commit 35d2b23

Browse files
committed
Fixed enumerators and added observables
1 parent 844da3d commit 35d2b23

32 files changed

+1207
-106
lines changed

Simple.Data.Ado.Test/AdoAdapterExceptionTest.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System;
44
using System.Collections.Generic;
55
using System.Data.SqlClient;
6+
using System.IO;
67
using NUnit.Framework;
78

89
[TestFixture]
@@ -63,5 +64,25 @@ public void StringAndStringAndDictionaryConstructorShouldSetMessageAndCommandTex
6364
Assert.AreEqual("Bar", actual.CommandText);
6465
Assert.AreEqual("quux", actual.Parameters["P"]);
6566
}
67+
68+
[Test]
69+
public void SerializationTest()
70+
{
71+
var param = new Dictionary<string, object> { { "P", "quux" } };
72+
var source = new AdoAdapterException("Foo", param);
73+
74+
var stream = new MemoryStream();
75+
var serializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
76+
serializer.Serialize(stream, source);
77+
78+
stream.Position = 0;
79+
80+
var actual = serializer.Deserialize(stream) as AdoAdapterException;
81+
82+
Assert.IsNotNull(actual);
83+
Assert.AreEqual(typeof(AdoAdapter), actual.AdapterType);
84+
Assert.AreEqual("Foo", actual.CommandText);
85+
Assert.AreEqual("quux", actual.Parameters["P"]);
86+
}
6687
}
6788
}

Simple.Data.Ado/AdoAdapter.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,6 @@ public override Func<object[],IDictionary<string,object>> CreateFindOneDelegate(
8686
return _finder.CreateFindOneDelegate(tableName, criteria);
8787
}
8888

89-
public override Func<object[], IEnumerable<IDictionary<string, object>>> CreateFindDelegate(string tableName, SimpleExpression criteria)
90-
{
91-
return _finder.CreateFindDelegate(tableName, criteria);
92-
}
93-
9489
public override IEnumerable<IDictionary<string, object>> Find(string tableName, SimpleExpression criteria)
9590
{
9691
return _finder.Find(tableName, criteria);
@@ -101,7 +96,15 @@ public override IEnumerable<IDictionary<string, object>> RunQuery(SimpleQuery qu
10196
var connection = _connectionProvider.CreateConnection();
10297
return new QueryBuilder(this).Build(query)
10398
.GetCommand(connection)
104-
.ToBufferedEnumerable(connection);
99+
.ToEnumerable(connection);
100+
}
101+
102+
public override IObservable<IDictionary<string, object>> RunQueryAsObservable(SimpleQuery query)
103+
{
104+
var connection = _connectionProvider.CreateConnection();
105+
return new QueryBuilder(this).Build(query)
106+
.GetCommand(connection)
107+
.ToObservable(connection, this);
105108
}
106109

107110
public override IDictionary<string, object> Insert(string tableName, IDictionary<string, object> data)

Simple.Data.Ado/AdoAdapterException.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace Simple.Data.Ado
1010
{
11+
[Serializable]
1112
public class AdoAdapterException : AdapterException
1213
{
1314
private readonly string _commandText;
@@ -49,6 +50,32 @@ public AdoAdapterException(string message, Exception inner) : base(message, inne
4950

5051
public AdoAdapterException(SerializationInfo info, StreamingContext context) : base(info, context)
5152
{
53+
_commandText = info.GetString("_commandText");
54+
try
55+
{
56+
var array = info.GetValue("_parameters", typeof (KeyValuePair<string, object>[]));
57+
if (array != null)
58+
{
59+
_parameters = ((KeyValuePair<string, object>[]) array).ToDictionary();
60+
}
61+
}
62+
catch (SerializationException)
63+
{
64+
}
65+
}
66+
67+
public override void GetObjectData(SerializationInfo info, StreamingContext context)
68+
{
69+
base.GetObjectData(info, context);
70+
info.AddValue("_commandText", _commandText);
71+
if (_parameters != null)
72+
{
73+
info.AddValue("_parameters", _parameters.ToArray(), typeof(KeyValuePair<string,object>[]));
74+
}
75+
else
76+
{
77+
info.AddValue("_parameters", null);
78+
}
5279
}
5380

5481
public IDictionary<string, object> Parameters

Simple.Data.Ado/AdoAdapterFinder.cs

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,6 @@ public IEnumerable<IDictionary<string, object>> Find(string tableName, SimpleExp
5656
return ExecuteQuery(commandTemplate, criteria.GetValues());
5757
}
5858

59-
public Func<object[], IEnumerable<IDictionary<string, object>>> CreateFindDelegate(string tableName, SimpleExpression criteria)
60-
{
61-
if (criteria == null)
62-
{
63-
return _ => FindAll(ObjectName.Parse(tableName));
64-
}
65-
var commandTemplate = GetCommandTemplate(tableName, criteria);
66-
return args => ExecuteQuery(commandTemplate, args);
67-
}
68-
6959
private CommandTemplate GetCommandTemplate(string tableName, SimpleExpression criteria)
7060
{
7161
var tableCommandCache = _commandCaches.GetOrAdd(tableName,
@@ -112,7 +102,7 @@ private static IEnumerable<IDictionary<string, object>> TryExecuteQuery(IDbConne
112102
{
113103
try
114104
{
115-
return command.ToBufferedEnumerable(connection);
105+
return command.ToEnumerable(connection);
116106
}
117107
catch (DbException ex)
118108
{
@@ -124,40 +114,14 @@ private static IEnumerable<IDictionary<string, object>> TryExecuteQuery(IDbConne
124114
{
125115
try
126116
{
127-
return command.ToBufferedEnumerable(connection, index);
117+
return command.ToEnumerable(connection, index);
128118
}
129119
catch (DbException ex)
130120
{
131121
throw new AdoAdapterException(ex.Message, command);
132122
}
133123
}
134124

135-
private static IDictionary<string, object> TryExecuteSingletonQuery(IDbConnection connection, IDbCommand command)
136-
{
137-
try
138-
{
139-
using (connection)
140-
using (command)
141-
{
142-
if (connection.State != ConnectionState.Open)
143-
connection.Open();
144-
using (var reader = command.ExecuteReader())
145-
{
146-
if (reader.Read())
147-
{
148-
var index = reader.CreateDictionaryIndex();
149-
return reader.ToDictionary(index);
150-
}
151-
}
152-
}
153-
}
154-
catch (DbException ex)
155-
{
156-
throw new AdoAdapterException(ex.Message, command);
157-
}
158-
return null;
159-
}
160-
161125
private static IDictionary<string, object> TryExecuteSingletonQuery(IDbConnection connection, IDbCommand command, IDictionary<string,int> index)
162126
{
163127
command.WriteTrace();
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace Simple.Data.Ado
7+
{
8+
using System.Collections;
9+
using System.Data;
10+
using System.Data.Common;
11+
12+
class DataReaderEnumerator : IEnumerator<IDictionary<string,object>>
13+
{
14+
private readonly IDbConnection _connection;
15+
private IDictionary<string, int> _index;
16+
private readonly IDbCommand _command;
17+
private IDataReader _reader;
18+
private bool _lastRead;
19+
20+
public DataReaderEnumerator(IDbCommand command, IDbConnection connection) : this(command, connection, null)
21+
{
22+
}
23+
24+
public DataReaderEnumerator(IDbCommand command, IDbConnection connection, IDictionary<string,int> index)
25+
{
26+
_command = command;
27+
_connection = connection;
28+
_index = index;
29+
}
30+
31+
public void Dispose()
32+
{
33+
using (_connection)
34+
using (_command)
35+
using (_reader)
36+
{ /* NO-OP */ }
37+
}
38+
39+
public bool MoveNext()
40+
{
41+
if (_reader == null)
42+
{
43+
ExecuteReader();
44+
}
45+
return _lastRead = _reader.Read();
46+
}
47+
48+
private void ExecuteReader()
49+
{
50+
try
51+
{
52+
if (_connection.State == ConnectionState.Closed)
53+
_connection.Open();
54+
_reader = _command.ExecuteReader();
55+
_index = _index ?? _reader.CreateDictionaryIndex();
56+
}
57+
catch (DbException ex)
58+
{
59+
throw new AdoAdapterException(ex.Message, ex);
60+
}
61+
}
62+
63+
public void Reset()
64+
{
65+
if (_reader != null) _reader.Dispose();
66+
ExecuteReader();
67+
}
68+
69+
public IDictionary<string, object> Current
70+
{
71+
get
72+
{
73+
if (!_lastRead) throw new InvalidOperationException();
74+
return _reader.ToDictionary();
75+
}
76+
}
77+
78+
object IEnumerator.Current
79+
{
80+
get { return Current; }
81+
}
82+
}
83+
}

Simple.Data.Ado/DataRecordExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace Simple.Data.Ado
88
{
9-
internal static class DataRecordExtensions
9+
public static class DataRecordExtensions
1010
{
1111
public static dynamic ToDynamicRecord(this IDataRecord dataRecord)
1212
{
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace Simple.Data.Ado
7+
{
8+
class DatabaseObservable
9+
{
10+
}
11+
}
Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,33 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Data;
4-
using System.Data.Common;
5-
using System.Linq;
6-
using System.Reflection;
7-
using System.Text;
8-
using Simple.Data.Extensions;
9-
10-
namespace Simple.Data.Ado
1+
namespace Simple.Data.Ado
112
{
3+
using System;
4+
using System.Collections;
5+
using System.Collections.Generic;
6+
using System.Data;
7+
using System.Data.Common;
8+
using System.Linq;
9+
1210
static class DbCommandExtensions
1311
{
14-
public static IEnumerable<IDictionary<string, object>> ToBufferedEnumerable(this IDbCommand command, IDbConnection connection)
12+
public static IEnumerable<IDictionary<string, object>> ToEnumerable(this IDbCommand command, IDbConnection connection)
1513
{
16-
try
17-
{
18-
if (connection.State == ConnectionState.Closed)
19-
connection.Open();
20-
}
21-
catch (DbException ex)
22-
{
23-
throw new AdoAdapterException(ex.Message, ex);
24-
}
25-
var reader = command.ExecuteReaderWithExceptionWrap();
26-
var index = reader.CreateDictionaryIndex();
27-
return BufferedEnumerable.Create(() => reader.Read()
28-
? Maybe.Some(reader.ToDictionary(index))
29-
: Maybe<IDictionary<string, object>>.None,
30-
() => DisposeCommandAndReader(connection, command, reader));
14+
return ToEnumerable(command, connection, null);
3115
}
3216

33-
public static IEnumerable<IDictionary<string, object>> ToBufferedEnumerable(this IDbCommand command, IDbConnection connection, IDictionary<string,int> index)
17+
public static IEnumerable<IDictionary<string, object>> ToEnumerable(this IDbCommand command, IDbConnection connection, IDictionary<string, int> index)
3418
{
35-
try
36-
{
37-
if (connection.State == ConnectionState.Closed)
38-
connection.Open();
39-
}
40-
catch (DbException ex)
41-
{
42-
throw new AdoAdapterException(ex.Message, ex);
43-
}
44-
var reader = command.ExecuteReaderWithExceptionWrap();
45-
return BufferedEnumerable.Create(() => reader.Read()
46-
? Maybe.Some(reader.ToDictionary(index))
47-
: Maybe<IDictionary<string, object>>.None,
48-
() => DisposeCommandAndReader(connection, command, reader));
19+
return new DataReaderEnumerator(command, connection, index).Wrap();
20+
}
21+
22+
public static IObservable<IDictionary<string, object>> ToObservable(this IDbCommand command, IDbConnection connection, AdoAdapter adapter)
23+
{
24+
return ToObservable(command, connection, adapter, null);
25+
}
26+
27+
public static IObservable<IDictionary<string, object>> ToObservable(this IDbCommand command, IDbConnection connection, AdoAdapter adapter, IDictionary<string, int> index)
28+
{
29+
var runner = adapter.ProviderHelper.GetCustomProvider<IObservableQueryRunner>(adapter.ConnectionProvider) ?? new ObservableQueryRunner();
30+
return runner.Run(command, connection, index);
4931
}
5032

5133
public static IDbDataParameter AddParameter(this IDbCommand command, string name, object value)
@@ -72,12 +54,39 @@ public static IDataReader ExecuteReaderWithExceptionWrap(this IDbCommand command
7254
}
7355
}
7456

75-
private static void DisposeCommandAndReader(IDbConnection connection, IDbCommand command, IDataReader reader)
57+
internal static void DisposeCommandAndReader(IDbConnection connection, IDbCommand command, IDataReader reader)
7658
{
7759
using (connection)
7860
using (command)
7961
using (reader)
8062
{ /* NoOp */ }
8163
}
8264
}
65+
66+
class EnumerableShim<T> : IEnumerable<T>
67+
{
68+
private readonly IEnumerator<T> _enumerator;
69+
public EnumerableShim(IEnumerator<T> enumerator)
70+
{
71+
_enumerator = enumerator;
72+
}
73+
74+
public IEnumerator<T> GetEnumerator()
75+
{
76+
return _enumerator;
77+
}
78+
79+
IEnumerator IEnumerable.GetEnumerator()
80+
{
81+
return GetEnumerator();
82+
}
83+
}
84+
85+
static class EnumerableShim
86+
{
87+
public static IEnumerable<T> Wrap<T>(this IEnumerator<T> enumerator)
88+
{
89+
return new EnumerableShim<T>(enumerator);
90+
}
91+
}
8392
}

0 commit comments

Comments
 (0)