Commit db1c00a8 authored by Sam Saffron's avatar Sam Saffron

Added support for a multi mapping grid reader

parent d9ef0084
...@@ -214,6 +214,12 @@ internal Identity ForGrid(Type primaryType, int gridIndex) ...@@ -214,6 +214,12 @@ internal Identity ForGrid(Type primaryType, int gridIndex)
{ {
return new Identity(sql, connectionString, primaryType, parametersType, null, gridIndex); return new Identity(sql, connectionString, primaryType, parametersType, null, gridIndex);
} }
internal Identity ForGrid(Type primaryType, Type[] otherTypes, int gridIndex)
{
return new Identity(sql, connectionString, primaryType, parametersType, otherTypes, gridIndex);
}
internal Identity(string sql, IDbConnection connection, Type type, Type parametersType, Type[] otherTypes) internal Identity(string sql, IDbConnection connection, Type type, Type parametersType, Type[] otherTypes)
: this(sql, connection.ConnectionString, type, parametersType, otherTypes, 0) : this(sql, connection.ConnectionString, type, parametersType, otherTypes, 0)
{ } { }
...@@ -473,19 +479,27 @@ class DontMap { } ...@@ -473,19 +479,27 @@ class DontMap { }
static IEnumerable<TReturn> MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>( static IEnumerable<TReturn> MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(
this IDbConnection cnn, string sql, object map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType) this IDbConnection cnn, string sql, object map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType)
{ {
var results = MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(cnn, sql, map, param, transaction, splitOn, commandTimeout, commandType); var results = MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(cnn, sql, map, param, transaction, splitOn, commandTimeout, commandType, null, null);
return buffered ? results.ToList() : results; return buffered ? results.ToList() : results;
} }
static IEnumerable<TReturn> MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(this IDbConnection cnn, string sql, object map, object param, IDbTransaction transaction, string splitOn, int? commandTimeout, CommandType? commandType) static IEnumerable<TReturn> MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(this IDbConnection cnn, string sql, object map, object param, IDbTransaction transaction, string splitOn, int? commandTimeout, CommandType? commandType, IDataReader reader, Identity identity)
{ {
Identity identity = new Identity(sql, cnn, typeof(TFirst), (object)param == null ? null : ((object)param).GetType(), new[] { typeof(TFirst), typeof(TSecond), typeof(TThird), typeof(TFourth), typeof(TFifth) }); identity = identity ?? new Identity(sql, cnn, typeof(TFirst), (object)param == null ? null : ((object)param).GetType(), new[] { typeof(TFirst), typeof(TSecond), typeof(TThird), typeof(TFourth), typeof(TFifth) });
CacheInfo info = GetCacheInfo(identity); CacheInfo info = GetCacheInfo(identity);
using (var cmd = SetupCommand(cnn, transaction, sql, info.ParamReader, (object)param, commandTimeout, commandType)) IDbCommand ownedCommand = null;
IDataReader ownedReader = null;
try
{ {
using (var reader = cmd.ExecuteReader()) if (reader == null)
{ {
ownedCommand = SetupCommand(cnn, transaction, sql, info.ParamReader, (object)param, commandTimeout, commandType);
ownedReader = ownedCommand.ExecuteReader();
reader = ownedReader;
}
if (info.Deserializer == null) if (info.Deserializer == null)
{ {
int current = 0; int current = 0;
...@@ -605,6 +619,22 @@ class DontMap { } ...@@ -605,6 +619,22 @@ class DontMap { }
} }
} }
} }
finally
{
try
{
if (ownedReader != null)
{
ownedReader.Dispose();
}
}
finally
{
if (ownedCommand != null)
{
ownedCommand.Dispose();
}
}
} }
} }
...@@ -1254,6 +1284,7 @@ public class GridReader : IDisposable ...@@ -1254,6 +1284,7 @@ public class GridReader : IDisposable
private IDataReader reader; private IDataReader reader;
private IDbCommand command; private IDbCommand command;
private Identity identity; private Identity identity;
internal GridReader(IDbCommand command, IDataReader reader, Identity identity) internal GridReader(IDbCommand command, IDataReader reader, Identity identity)
{ {
this.command = command; this.command = command;
...@@ -1279,7 +1310,63 @@ public IEnumerable<T> Read<T>() ...@@ -1279,7 +1310,63 @@ public IEnumerable<T> Read<T>()
return ReadDeferred(gridIndex, deserializer, typedIdentity); return ReadDeferred(gridIndex, deserializer, typedIdentity);
} }
// todo multimapping. private IEnumerable<TReturn> MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(object func, string splitOn)
{
var identity = this.identity.ForGrid(typeof(TReturn), new Type[] {
typeof(TFirst),
typeof(TSecond),
typeof(TThird),
typeof(TFourth),
typeof(TFifth)
}, gridIndex);
try
{
foreach (var r in SqlMapper.MultiMapImpl<TFirst, TSecond, DontMap, DontMap, DontMap, TReturn>(null, null, func, null, null, splitOn, null, null, reader, identity))
{
yield return r;
}
}
finally
{
NextResult();
}
}
#if CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn)
#else
public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn = "id")
#endif
{
return MultiReadInternal<TFirst, TSecond, DontMap, DontMap, DontMap, TReturn>(func, splitOn);
}
#if CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn)
#else
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn = "id")
#endif
{
return MultiReadInternal<TFirst, TSecond, TThird, DontMap, DontMap, TReturn>(func, splitOn);
}
#if CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn)
#else
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn = "id")
#endif
{
return MultiReadInternal<TFirst, TSecond, TThird, TFourth, DontMap, TReturn>(func, splitOn);
}
#if !CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> func, string splitOn = "id")
{
return MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(func, splitOn);
}
#endif
private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, T> deserializer, Identity typedIdentity) private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, T> deserializer, Identity typedIdentity)
{ {
......
...@@ -348,6 +348,51 @@ public void TestMultiMap() ...@@ -348,6 +348,51 @@ public void TestMultiMap()
} }
public void TestMultiMapGridReader()
{
var createSql = @"
create table #Users (Id int, Name varchar(20))
create table #Posts (Id int, OwnerId int, Content varchar(20))
insert #Users values(99, 'Sam')
insert #Users values(2, 'I am')
insert #Posts values(1, 99, 'Sams Post1')
insert #Posts values(2, 99, 'Sams Post2')
insert #Posts values(3, null, 'no ones post')
";
connection.Execute(createSql);
var sql =
@"select p.*, u.Id, u.Name + '0' Name from #Posts p
left join #Users u on u.Id = p.OwnerId
Order by p.Id
select p.*, u.Id, u.Name + '1' Name from #Posts p
left join #Users u on u.Id = p.OwnerId
Order by p.Id
";
var grid = connection.QueryMultiple(sql);
for (int i = 0; i < 2; i++)
{
var data = grid.Read<Post, User, Post>((post, user) => { post.Owner = user; return post; }).ToList();
var p = data.First();
p.Content.IsEqualTo("Sams Post1");
p.Id.IsEqualTo(1);
p.Owner.Name.IsEqualTo("Sam" + i);
p.Owner.Id.IsEqualTo(99);
data[2].Owner.IsNull();
}
connection.Execute("drop table #Users drop table #Posts");
}
public void TestMultiMapDynamic() public void TestMultiMapDynamic()
{ {
var createSql = @" var createSql = @"
...@@ -810,6 +855,7 @@ public void ParentChildIdentityAssociations() ...@@ -810,6 +855,7 @@ public void ParentChildIdentityAssociations()
parents[3].Children.Select(c => c.Id).SequenceEqual(new[] { 5 }).IsTrue(); parents[3].Children.Select(c => c.Id).SequenceEqual(new[] { 5 }).IsTrue();
} }
/* TODO: /* TODO:
* *
public void TestMagicParam() public void TestMagicParam()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment