Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 45 additions & 9 deletions Dapper/DynamicParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
/// <summary>
/// All the names of the param in the bag, use Get to yank them out
/// </summary>
public IEnumerable<string> ParameterNames => parameters.Select(p => p.Key);
public IEnumerable<string> ParameterNames => GetParamNames();

/// <summary>
/// Get the value of a parameter
Expand All @@ -315,18 +315,41 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
/// <returns>The value, note DBNull.Value is not returned, instead the value is returned as null</returns>
public T Get<T>(string name)
{
var paramInfo = parameters[Clean(name)];
var attachedParam = paramInfo.AttachedParam;
object? val = attachedParam is null ? paramInfo.Value : attachedParam.Value;
if (val == DBNull.Value)
var cleanName = Clean(name);
if (parameters.TryGetValue(cleanName, out var paramInfo))
{
if (default(T) is not null)
object? val = paramInfo!.AttachedParam is null ? paramInfo.Value : paramInfo.AttachedParam.Value;
if (val == DBNull.Value)
{
throw new ApplicationException("Attempting to cast a DBNull to a non nullable type! Note that out/return parameters will not have updated values until the data stream completes (after the 'foreach' for Query(..., buffered: false), or after the GridReader has been disposed for QueryMultiple)");
if (default(T) is not null)
{
throw new ApplicationException("Attempting to cast a DBNull to a non nullable type! Note that out/return parameters will not have updated values until the data stream completes (after the 'foreach' for Query(..., buffered: false), or after the GridReader has been disposed for QueryMultiple)");
}
return default!;
}
return default!;
return (T)val!;
}
return (T)val!;
if (templates != null)
{
var foundValue = templates
.Select(obj => obj?.GetType().GetProperty(cleanName)?.GetValue(obj))
.FirstOrDefault(value => value != null);

if (foundValue != null)
{
if (foundValue == DBNull.Value)
{
if (default(T) is not null)
{
throw new ApplicationException("Attempting to cast a DBNull to a non nullable type! Note that out/return parameters will not have updated values until the data stream completes (after the 'foreach' for Query(..., buffered: false), or after the GridReader has been disposed for QueryMultiple)");
}
return default!;
}
return (T)foundValue;
}
}

throw new KeyNotFoundException($"Key {name} could not be found in param list.");
}

/// <summary>
Expand Down Expand Up @@ -496,5 +519,18 @@ void SqlMapper.IParameterCallbacks.OnCompleted()
param.OutputCallback?.Invoke(param.OutputTarget, this);
}
}
private List<string> GetParamNames()
{
var paramBagItems = parameters.Select(p => p.Key);
var propNames = new List<string>();
if(templates != null)
{
var templateProps = templates.SelectMany(obj => obj.GetType().GetProperties());
propNames.AddRange(templateProps.Select(prop => prop.Name).Distinct());
}

propNames.AddRange(paramBagItems);
return propNames;
}
}
}
62 changes: 62 additions & 0 deletions tests/Dapper.Tests/ParameterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,68 @@ public void TestTVP()
}
}
}
[Fact]
public void TestGetSqlBuilderParamNames()
{
var sqlBuilder = new SqlBuilder();

var templateA = sqlBuilder.AddTemplate("SELECT @a", new
{
a = 1
});
var templateB = sqlBuilder.AddTemplate("SELECT @b", new
{
b = 2
});
sqlBuilder.AddParameters(new
{
c = 3
});

var aParameters = new DynamicParameters(templateA.Parameters);
var aParamNames = aParameters.ParameterNames;

var bParameters = new DynamicParameters(templateB.Parameters);
var bParamNames = bParameters.ParameterNames;

Assert.Contains("a", aParamNames);
Assert.DoesNotContain("b", aParamNames);
Assert.Contains("c", aParamNames);
Assert.DoesNotContain("a", bParamNames);
Assert.Contains("b", bParamNames);
Assert.Contains("c", bParamNames);
}
[Fact]
public void TestGetSqlBuilderParams()
{
var sqlBuilder = new SqlBuilder();

var templateA = sqlBuilder.AddTemplate("SELECT @a", new
{
a = 1
});
var templateB = sqlBuilder.AddTemplate("SELECT @b", new
{
b = 2
});
sqlBuilder.AddParameters(new
{
c = 3
});

var aParameters = new DynamicParameters(templateA.Parameters);
var bParameters = new DynamicParameters(templateB.Parameters);

var aParamValue = aParameters.Get<int>("a");
var bParamValue = bParameters.Get<int>("b");
var cParamValueA = aParameters.Get<int>("c");
var cParamValueB = bParameters.Get<int>("c");

Assert.Equal(1, aParamValue);
Assert.Equal(2, bParamValue);
Assert.Equal(3, cParamValueA);
Assert.Equal(3, cParamValueB);
}

private class DynamicParameterWithIntTVP : DynamicParameters, SqlMapper.IDynamicParameters
{
Expand Down