Skip to content

Commit d8f14dc

Browse files
authored
Merge pull request #18 from adriangodong/v2
Implement classes purely from interfaces
2 parents 81ade4e + c3ecac6 commit d8f14dc

24 files changed

+925
-573
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Added new interfaces: `S.D.A.IDataRecordAsync` (extends `IDataRecord`), `S.D.A.IDbDataReaderAsync`, `S.D.A.SqlClient.ISqlConnectionAsync`, `S.D.A.SqlClient.ISqlCommandAsync`, `S.D.A.SqlClient.ISqlDataReaderAsync`. [#18](https://github.com/adriangodong/system-data-async/pull/18)
13+
- Added new documentation on how the type hierarchy is written. [#18](https://github.com/adriangodong/system-data-async/pull/18)
14+
15+
### Changed
16+
17+
- `S.D.A.Common.DbConnectionAsync` no longer derived from `DbConnection`, forwards all public members to wrapped `DbConnection` instance instead. [#18](https://github.com/adriangodong/system-data-async/pull/18)
18+
- `S.D.A.Common.DbCommandAsync` no longer derived from `DbCommand`, forwards all public members to wrapped `DbCommand` instance instead. [#18](https://github.com/adriangodong/system-data-async/pull/18)
19+
- `S.D.A.SqlClient.SqlConnectionAsync` fully forwards all public members to wrapped `SqlConnection` instance. [#18](https://github.com/adriangodong/system-data-async/pull/18)
20+
- `S.D.A.SqlClient.SqlCommandAsync` fully forwards all public members to wrapped `SqlCommand` instance. [#18](https://github.com/adriangodong/system-data-async/pull/18)
21+
- `S.D.A.SqlClient.SqlDataReaderAsync` fully forwards all public members to wrapped `SqlDataReader` instance. [#18](https://github.com/adriangodong/system-data-async/pull/18)
22+
- Multiple changes in type hierarchy, public member additions and removals. [#18](https://github.com/adriangodong/system-data-async/pull/18)
23+
24+
### Removed
25+
26+
- `S.D.A.Common.DbDataReaderAsync` has been removed. This has always been a simple intermediate class and no longer needed. [#18](https://github.com/adriangodong/system-data-async/pull/18)
27+
1028
## [1.0.7] - 2018-12-19
1129

1230
### Added

README.md

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,52 @@
1-
This library adds interfaces and adapters to allow working with async methods available in System.Data abstract classes but not interfaces.
1+
# System.Data.Async
2+
3+
This library adds interfaces and adapters to allow working with async methods available in `System.Data` abstract classes but not interfaces.
4+
5+
**Latest Release**
6+
7+
[![Release](https://img.shields.io/nuget/v/MediumSdk.svg)](https://www.nuget.org/packages/MediumSdk/)
8+
9+
**Latest master Build**
10+
11+
[![Latest](https://ci.appveyor.com/api/projects/status/b5j0b5y7tm413mcw/branch/master?svg=true)](https://ci.appveyor.com/project/adriangodong/system-data-async/branch/master)
12+
213

314
## Sample migration
415

516
```diff
6-
- // With System.Data.Common
7-
+ // With System.Data.Async
8-
9-
- public Task<System.Data.Common.DbCommand> CreateCommand(System.Data.Common.DbConnection connection)
10-
+ public Task<System.Data.Async.IDbCommandAsync> CreateCommand(System.Data.Async.IDbConnectionAsync connection)
11-
{
12-
- System.Data.Common.DbCommand command = connection.CreateCommand();
13-
+ System.Data.Async.IDbCommandAsync command = connection.CreateCommand();
17+
- // With System.Data.Common
18+
+ // With System.Data.Async
19+
20+
// Construct a new Connection object.
21+
- System.Data.Common.SqlClient.SqlConnection connection =
22+
- new System.Data.SqlClient.SqlConnection("connection string");
23+
+ System.Data.Async.SqlClient.ISqlConnectionAsync connection =
24+
+ new System.Data.Async.SqlClient.SqlConnectionAsync("connection string");
25+
26+
// Construct a new Command object.
27+
- System.Data.Command.SqlClient.SqlCommand command = connection.CreateCommand();
28+
+ System.Data.Async.SqlClient.ISqlCommandAsync command = connection.CreateCommand();
29+
30+
// Open Connection.
1431
await connection.OpenAsync();
15-
return command;
16-
}
17-
18-
public void GetCommand()
19-
{
20-
- var connection = new System.Data.SqlClient.SqlConnection("connection string");
21-
+ var connection = new System.Data.Async.SqlClient.SqlConnectionAsync("connection string");
22-
CreateCommand(connection);
23-
}
32+
33+
// Get DataReader object.
34+
- System.Data.SqlClient.SqlDataReader reader = await command.ExecuteReaderAsync();
35+
+ System.Data.Async.SqlClient.SqlDataReaderAsync reader = await command.ExecuteReaderAsync();
2436
```
2537

26-
## [Changelog](CHANGELOG.md)
38+
39+
## Installation
40+
41+
* Get release packages from [NuGet](https://www.nuget.org/packages/System.Data.Async)
42+
* Get pre-release packages from AppVeyor NuGet Feed
43+
* Feed URL: `https://ci.appveyor.com/nuget/system-data-async`
44+
45+
46+
## Documentation
47+
48+
* [Changelog](CHANGELOG.md)
49+
* [General Approach](docs/GeneralApproach.md)
50+
* [Connection Objects](docs/Connection.md)
51+
* [Command Objects](docs/Command.md)
52+
* [DataReader Objects](docs/DataReader.md)

Samples/LocalDb/LeakTests.cs

Lines changed: 43 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
1+
using System.Collections.Generic;
32
using System.Data;
43
using System.Data.Async;
54
using System.Data.Async.SqlClient;
@@ -12,7 +11,7 @@ namespace LocalDb
1211
public class LeakTests
1312
{
1413

15-
private IDbConnectionAsync GetConnection()
14+
private ISqlConnectionAsync GetConnection()
1615
{
1716
return new SqlConnectionAsync("Server=(localdb)\\MSSQLLocalDB;Integrated Security=true;");
1817
}
@@ -29,27 +28,23 @@ private DbmsDatatypeMapping Read(IDataReaderAsync reader)
2928
}
3029

3130
[TestMethod]
32-
public async Task SqlCommandAsync_Dispose_ShouldCloseConnectionAndNullify()
31+
public async Task SqlCommandAsync_Dispose_ShouldNotCloseConnection()
3332
{
3433
// Arrange
3534
var connection = GetConnection();
3635
var command = connection.CreateCommand();
3736

38-
var innerConnection = ((SqlConnectionAsync)connection).sqlConnection;
39-
4037
await connection.OpenAsync();
4138

4239
// Act
4340
command.Dispose();
4441

4542
// Assert
46-
Assert.AreEqual(ConnectionState.Closed, innerConnection.State);
47-
Assert.IsNull(((SqlCommandAsync)command).sqlCommand);
48-
Assert.IsNull(((SqlCommandAsync)command).sqlConnectionAsync);
43+
Assert.AreEqual(ConnectionState.Open, connection.State);
4944
}
5045

5146
[TestMethod]
52-
public async Task SqlDataReaderAsync_Dispose_ShouldCloseConnectionAndNullify()
47+
public async Task SqlDataReaderAsync_Dispose_ShouldNotCloseConnection()
5348
{
5449
// Arrange
5550
var connection = GetConnection();
@@ -64,8 +59,26 @@ public async Task SqlDataReaderAsync_Dispose_ShouldCloseConnectionAndNullify()
6459
reader.Dispose();
6560

6661
// Assert
67-
Assert.IsNull(((SqlDataReaderAsync)reader).sqlDataReader);
68-
Assert.IsNull(((SqlDataReaderAsync)reader).sqlCommandAsync);
62+
Assert.AreEqual(ConnectionState.Open, connection.State);
63+
}
64+
65+
[TestMethod]
66+
public async Task SqlDataReaderAsync_CommandBehavior_CloseConnection_Dispose_ShouldCloseConnection()
67+
{
68+
// Arrange
69+
var connection = GetConnection();
70+
var command = connection.CreateCommand();
71+
command.CommandText = "select * from msdb.dbo.MSdbms_datatype_mapping";
72+
command.CommandType = CommandType.Text;
73+
74+
await connection.OpenAsync();
75+
var reader = await command.ExecuteReaderAsync(CommandBehavior.CloseConnection);
76+
77+
// Act
78+
reader.Dispose();
79+
80+
// Assert
81+
Assert.AreEqual(ConnectionState.Closed, connection.State);
6982
}
7083

7184
[TestMethod]
@@ -91,47 +104,30 @@ public async Task Using_ExecuteReaderAsync_CommandBehavior_CloseConnection_LeakT
91104
}
92105
}
93106

94-
[TestMethod]
95-
public async Task Using_ExecuteReaderAsync_WithGcCollect_LeakTest()
96-
{
97-
var connection = GetConnection();
98-
var command = connection.CreateCommand();
99-
command.CommandText = "select * from msdb.dbo.MSdbms_datatype_mapping";
100-
command.CommandType = CommandType.Text;
101-
102-
await connection.OpenAsync();
103-
104-
var mappings = new List<DbmsDatatypeMapping>();
105-
using (var reader = await command.ExecuteReaderAsync(CommandBehavior.CloseConnection))
106-
{
107-
while (await reader.ReadAsync())
108-
{
109-
GC.Collect();
110-
mappings.Add(Read(reader));
111-
}
112-
}
113-
}
114-
115107
[TestMethod]
116108
public async Task Using_ExecuteReaderAsync_LeakTest()
117109
{
118110
for (var i = 0; i < 1000; i++)
119111
{
120-
var connection = GetConnection();
121-
var command = connection.CreateCommand();
122-
command.CommandText = "select * from msdb.dbo.MSdbms_datatype_mapping";
123-
command.CommandType = CommandType.Text;
124-
125-
await connection.OpenAsync();
126-
127-
var mappings = new List<DbmsDatatypeMapping>();
128-
using (var reader = await command.ExecuteReaderAsync())
112+
using (var connection = GetConnection())
129113
{
130-
while (await reader.ReadAsync())
114+
using (var command = connection.CreateCommand())
131115
{
132-
while (await reader.ReadAsync())
116+
command.CommandText = "select * from msdb.dbo.MSdbms_datatype_mapping";
117+
command.CommandType = CommandType.Text;
118+
119+
await connection.OpenAsync();
120+
121+
var mappings = new List<DbmsDatatypeMapping>();
122+
using (var reader = await command.ExecuteReaderAsync())
133123
{
134-
mappings.Add(Read(reader));
124+
while (await reader.ReadAsync())
125+
{
126+
while (await reader.ReadAsync())
127+
{
128+
mappings.Add(Read(reader));
129+
}
130+
}
135131
}
136132
}
137133
}
@@ -160,29 +156,6 @@ public async Task Dispose_ExecuteReaderAsync_CommandBehavior_CloseConnection_Lea
160156
}
161157
}
162158

163-
[TestMethod]
164-
public async Task Dispose_ExecuteReaderAsync_WithGcCollect_LeakTest()
165-
{
166-
var connection = GetConnection();
167-
var command = connection.CreateCommand();
168-
command.CommandText = "select * from msdb.dbo.MSdbms_datatype_mapping";
169-
command.CommandType = CommandType.Text;
170-
171-
await connection.OpenAsync();
172-
173-
var mappings = new List<DbmsDatatypeMapping>();
174-
var reader = await command.ExecuteReaderAsync();
175-
while (await reader.ReadAsync())
176-
{
177-
while (await reader.ReadAsync())
178-
{
179-
GC.Collect();
180-
mappings.Add(Read(reader));
181-
}
182-
}
183-
reader.Dispose();
184-
}
185-
186159
[TestMethod]
187160
public async Task Dispose_ExecuteReaderAsync_LeakTest()
188161
{
@@ -205,6 +178,8 @@ public async Task Dispose_ExecuteReaderAsync_LeakTest()
205178
}
206179
}
207180
reader.Dispose();
181+
command.Dispose();
182+
connection.Dispose();
208183
}
209184
}
210185

Samples/Moq/Moq.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Data.Async;
1+
using System.Data;
2+
using System.Data.Async;
23
using System.Threading.Tasks;
34
using Microsoft.VisualStudio.TestTools.UnitTesting;
45

@@ -67,20 +68,20 @@ public async Task CreateCommand_ExecuteScalarAsync()
6768
}
6869

6970
[TestMethod]
70-
public async Task CreateCommand_ExecuteReader_ReadAsync()
71+
public void CreateCommand_ExecuteReader_Read()
7172
{
7273
// Arrange
7374
var mockConnection = new Mock<IDbConnectionAsync>();
7475
var mockCommand = new Mock<IDbCommandAsync>();
75-
var mockDataReader = new Mock<IDataReaderAsync>();
76+
var mockDataReader = new Mock<IDataReader>();
7677
mockConnection.Setup(mock => mock.CreateCommand()).Returns(mockCommand.Object);
7778
mockCommand.Setup(mock => mock.ExecuteReader()).Returns(mockDataReader.Object);
7879

7980
// Act
80-
await mockConnection.Object.CreateCommand().ExecuteReader().ReadAsync();
81+
mockConnection.Object.CreateCommand().ExecuteReader().Read();
8182

8283
// Assert
83-
mockDataReader.Verify(mock => mock.ReadAsync(), Times.Once);
84+
mockDataReader.Verify(mock => mock.Read(), Times.Once);
8485
}
8586

8687
[TestMethod]
@@ -89,7 +90,7 @@ public async Task CreateCommand_ExecuteReaderAsync_ReadAsync()
8990
// Arrange
9091
var mockConnection = new Mock<IDbConnectionAsync>();
9192
var mockCommand = new Mock<IDbCommandAsync>();
92-
var mockDataReader = new Mock<IDataReaderAsync>();
93+
var mockDataReader = new Mock<IDbDataReaderAsync>();
9394
mockConnection.Setup(mock => mock.CreateCommand()).Returns(mockCommand.Object);
9495
mockCommand.Setup(mock => mock.ExecuteReaderAsync()).ReturnsAsync(mockDataReader.Object);
9596

System.Data.Async/AssemblyInfo.cs

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)