AddWithValue via Extension Methods
On a recent .NET Rocks panel show, Ayende complained that the abstract classes to access databases (for example, IDbCommand) were lacking some fundamental pieces that make the concrete classes (eg SqlCommand) easier to use. The example he cited was the AddWithValue method, to quickly add a parameter to an SqlCommand along with its value.
I know how he feels; the act of calling CreateParameter, then setting the parameter's name and value, then calling Parameters.Add is a lot more code than it should be for such a simple operation.
So I've gone ahead and made myself a quartet of handy extension methods to give me similar functionality to the AddWithValue method. In fact, my version is a little more powerful, since it accepts nullable types and passes DBNull if the value isn't specified. Here's the code:
internal static class DbCommandExtensions { internal static int AddInputParameter<T>(this IDbCommand cmd, string name, T value) { var p = cmd.CreateParameter(); p.ParameterName = name; p.Value = value; return cmd.Parameters.Add(p); } internal static int AddInputParameter<T>(this IDbCommand cmd, string name, Nullable<T> value) where T : struct { var p = cmd.CreateParameter(); p.ParameterName = name; p.Value = value.HasValue ? (object)value : DBNull.Value; return cmd.Parameters.Add(p); } internal static int AddInputParameter(this IDbCommand cmd, string name, string value) { var p = cmd.CreateParameter(); p.ParameterName = name; p.Value = string.IsNullOrEmpty(value) ? DBNull.Value : (object)value; return cmd.Parameters.Add(p); } internal static IDbDataParameter AddOutputParameter(this IDbCommand cmd, string name, DbType dbType) { var p = cmd.CreateParameter(); p.ParameterName = name; p.DbType = dbType; p.Direction = ParameterDirection.Output; cmd.Parameters.Add(p); return p; } }
So this gives us essentially two new methods on IDbCommand, "AddInputParameter" and "AddOutputParameter". You use them like this:
var cmd = _connection.CreateCommand(); cmd.AddInputParameter("@id", eventDate); var idParam = cmd.AddOutputParameter("@id", DbType.Guid);
Pretty straight forward, I think, and it saves a lot of code. It also hasn't broken any of our tests, because all the expectations we've set on our mocks are still being met.
# Trackback from Adding IDbCommand Parameters with Anonymous Types on 14/11/2008 1:52 PM
Comments
# John Kingston
26/09/2009 12:29 PM
Hi Matt - the solution I was looking for!
Only I went from clipper to vb.net
Didn't take much to get it working though: (needs framework 3.5)
regards, John
Imports System.Runtime.CompilerServices
Friend Module DbCommandExtensions
Sub New()
End Sub
<System.Runtime.CompilerServices.Extension()> _
Friend Function AddInputParameter(Of T)(ByVal cmd As IDbCommand, ByVal name As String, ByVal value As T) As Integer
Dim p = cmd.CreateParameter()
p.ParameterName = name
p.Value = value
Return cmd.Parameters.Add(p)
End Function
<System.Runtime.CompilerServices.Extension()> _
Friend Function AddInputParameter(Of T As Structure)(ByVal cmd As IDbCommand, ByVal name As String, ByVal value As Nullable(Of T)) As Integer
Dim p = cmd.CreateParameter()
p.ParameterName = name
p.Value = If(value.HasValue, DirectCast(value, Object), DBNull.Value)
Return cmd.Parameters.Add(p)
End Function
<System.Runtime.CompilerServices.Extension()> _
Friend Function AddInputParameter(ByVal cmd As IDbCommand, ByVal name As String, ByVal value As String) As Integer
Dim p = cmd.CreateParameter()
p.ParameterName = name
p.Value = If(String.IsNullOrEmpty(value), DBNull.Value, DirectCast(value, Object))
Return cmd.Parameters.Add(p)
End Function
<System.Runtime.CompilerServices.Extension()> _
Friend Function AddOutputParameter(ByVal cmd As IDbCommand, ByVal name As String, ByVal dbType As DbType) As IDbDataParameter
Dim p = cmd.CreateParameter()
p.ParameterName = name
p.DbType = dbType
p.Direction = ParameterDirection.Output
cmd.Parameters.Add(p)
Return p
End Function
End Module