Add object-based stored procedure parameter binding
This commit is contained in:
135
DynamORM.Tests/Helpers/FakeDbCommand.cs
Normal file
135
DynamORM.Tests/Helpers/FakeDbCommand.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* DynamORM - Dynamic Object-Relational Mapping library.
|
||||
* Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
|
||||
namespace DynamORM.Tests.Helpers
|
||||
{
|
||||
internal sealed class FakeDbCommand : IDbCommand
|
||||
{
|
||||
private readonly FakeParameterCollection _parameters = new FakeParameterCollection();
|
||||
|
||||
public string CommandText { get; set; }
|
||||
public int CommandTimeout { get; set; }
|
||||
public CommandType CommandType { get; set; }
|
||||
public IDbConnection Connection { get; set; }
|
||||
public IDataParameterCollection Parameters { get { return _parameters; } }
|
||||
public IDbTransaction Transaction { get; set; }
|
||||
public UpdateRowSource UpdatedRowSource { get; set; }
|
||||
|
||||
public void Cancel() { }
|
||||
public IDbDataParameter CreateParameter() { return new FakeDbParameter(); }
|
||||
public void Dispose() { }
|
||||
public int ExecuteNonQuery() { throw new NotSupportedException(); }
|
||||
public IDataReader ExecuteReader() { throw new NotSupportedException(); }
|
||||
public IDataReader ExecuteReader(CommandBehavior behavior) { throw new NotSupportedException(); }
|
||||
public object ExecuteScalar() { throw new NotSupportedException(); }
|
||||
public void Prepare() { }
|
||||
}
|
||||
|
||||
internal sealed class FakeDbParameter : IDbDataParameter
|
||||
{
|
||||
public byte Precision { get; set; }
|
||||
public byte Scale { get; set; }
|
||||
public int Size { get; set; }
|
||||
public DbType DbType { get; set; }
|
||||
public ParameterDirection Direction { get; set; }
|
||||
public bool IsNullable { get { return true; } }
|
||||
public string ParameterName { get; set; }
|
||||
public string SourceColumn { get; set; }
|
||||
public DataRowVersion SourceVersion { get; set; }
|
||||
public object Value { get; set; }
|
||||
}
|
||||
|
||||
internal sealed class FakeParameterCollection : IDataParameterCollection
|
||||
{
|
||||
private readonly List<object> _items = new List<object>();
|
||||
|
||||
public object this[string parameterName]
|
||||
{
|
||||
get { return _items.Find(x => string.Equals(((IDbDataParameter)x).ParameterName, parameterName, StringComparison.Ordinal)); }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
public object this[int index]
|
||||
{
|
||||
get { return _items[index]; }
|
||||
set { _items[index] = value; }
|
||||
}
|
||||
|
||||
public bool IsFixedSize { get { return false; } }
|
||||
public bool IsReadOnly { get { return false; } }
|
||||
public int Count { get { return _items.Count; } }
|
||||
public bool IsSynchronized { get { return false; } }
|
||||
public object SyncRoot { get { return this; } }
|
||||
|
||||
public int Add(object value)
|
||||
{
|
||||
_items.Add(value);
|
||||
return _items.Count - 1;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_items.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(string parameterName)
|
||||
{
|
||||
return _items.Exists(x => string.Equals(((IDbDataParameter)x).ParameterName, parameterName, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
public bool Contains(object value)
|
||||
{
|
||||
return _items.Contains(value);
|
||||
}
|
||||
|
||||
public void CopyTo(Array array, int index)
|
||||
{
|
||||
_items.ToArray().CopyTo(array, index);
|
||||
}
|
||||
|
||||
public IEnumerator GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
}
|
||||
|
||||
public int IndexOf(string parameterName)
|
||||
{
|
||||
return _items.FindIndex(x => string.Equals(((IDbDataParameter)x).ParameterName, parameterName, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
public int IndexOf(object value)
|
||||
{
|
||||
return _items.IndexOf(value);
|
||||
}
|
||||
|
||||
public void Insert(int index, object value)
|
||||
{
|
||||
_items.Insert(index, value);
|
||||
}
|
||||
|
||||
public void Remove(object value)
|
||||
{
|
||||
_items.Remove(value);
|
||||
}
|
||||
|
||||
public void RemoveAt(string parameterName)
|
||||
{
|
||||
int index = IndexOf(parameterName);
|
||||
if (index >= 0)
|
||||
_items.RemoveAt(index);
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
_items.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
DynamORM.Tests/Helpers/ProcedureParameterModels.cs
Normal file
31
DynamORM.Tests/Helpers/ProcedureParameterModels.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* DynamORM - Dynamic Object-Relational Mapping library.
|
||||
* Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
using System.Data;
|
||||
|
||||
namespace DynamORM.Tests.Helpers
|
||||
{
|
||||
public class ProcedureParameterObject
|
||||
{
|
||||
[ProcedureParameter("code", Order = 2, DbType = DbType.String, Size = 32)]
|
||||
public string Code { get; set; }
|
||||
|
||||
[ProcedureParameter("result", Direction = ParameterDirection.Output, Order = 3, DbType = DbType.Int32)]
|
||||
public int Result { get; set; }
|
||||
|
||||
[ProcedureParameter("description", Direction = ParameterDirection.InputOutput, Order = 4, DbType = DbType.String, Size = 256)]
|
||||
public string Description { get; set; }
|
||||
|
||||
[ProcedureParameter("status", Direction = ParameterDirection.ReturnValue, Order = 1)]
|
||||
public int Status { get; set; }
|
||||
}
|
||||
|
||||
public class ProcedureParameterColumnFallbackObject
|
||||
{
|
||||
[DynamORM.Mapper.Column("code", false, DbType.String, 64)]
|
||||
public string Code { get; set; }
|
||||
}
|
||||
}
|
||||
117
DynamORM.Tests/Procedure/ProcedureParameterBinderTests.cs
Normal file
117
DynamORM.Tests/Procedure/ProcedureParameterBinderTests.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* DynamORM - Dynamic Object-Relational Mapping library.
|
||||
* Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
using System.Data;
|
||||
using DynamORM.Helpers;
|
||||
using DynamORM.Tests.Helpers;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace DynamORM.Tests.Procedure
|
||||
{
|
||||
[TestFixture]
|
||||
public class ProcedureParameterBinderTests : TestsBase
|
||||
{
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
CreateTestDatabase();
|
||||
CreateDynamicDatabase(
|
||||
DynamicDatabaseOptions.SingleConnection |
|
||||
DynamicDatabaseOptions.SingleTransaction |
|
||||
DynamicDatabaseOptions.SupportStoredProcedures |
|
||||
DynamicDatabaseOptions.SupportStoredProceduresResult |
|
||||
DynamicDatabaseOptions.SupportSchema);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
DestroyDynamicDatabase();
|
||||
DestroyTestDatabase();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCanBindProcedureParameterObject()
|
||||
{
|
||||
Assert.IsTrue(DynamicProcedureParameterBinder.CanBind(new ProcedureParameterObject()));
|
||||
Assert.IsTrue(DynamicProcedureParameterBinder.CanBind(new ProcedureParameterColumnFallbackObject()));
|
||||
Assert.IsFalse(DynamicProcedureParameterBinder.CanBind("x"));
|
||||
Assert.IsFalse(DynamicProcedureParameterBinder.CanBind(5));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBindUsesAttributeMetadataAndOrder()
|
||||
{
|
||||
using (IDbCommand cmd = new FakeDbCommand())
|
||||
{
|
||||
var result = DynamicProcedureParameterBinder.Bind(Database, cmd, new ProcedureParameterObject
|
||||
{
|
||||
Code = "ABC",
|
||||
Description = "seed"
|
||||
});
|
||||
|
||||
Assert.IsTrue(result.ReturnValueAdded);
|
||||
Assert.NotNull(result.ReturnParameters);
|
||||
Assert.AreEqual(3, result.ReturnParameters.Count);
|
||||
Assert.AreEqual(4, cmd.Parameters.Count);
|
||||
|
||||
var p0 = (IDbDataParameter)cmd.Parameters[0];
|
||||
var p1 = (IDbDataParameter)cmd.Parameters[1];
|
||||
var p2 = (IDbDataParameter)cmd.Parameters[2];
|
||||
var p3 = (IDbDataParameter)cmd.Parameters[3];
|
||||
|
||||
Assert.AreEqual(Database.GetParameterName("status"), p0.ParameterName);
|
||||
Assert.AreEqual(ParameterDirection.ReturnValue, p0.Direction);
|
||||
Assert.AreEqual(DbType.Int32, p0.DbType);
|
||||
Assert.AreEqual(4, p0.Size);
|
||||
|
||||
Assert.AreEqual(Database.GetParameterName("code"), p1.ParameterName);
|
||||
Assert.AreEqual(ParameterDirection.Input, p1.Direction);
|
||||
Assert.AreEqual(DbType.String, p1.DbType);
|
||||
Assert.AreEqual(32, p1.Size);
|
||||
Assert.AreEqual("ABC", p1.Value);
|
||||
|
||||
Assert.AreEqual(Database.GetParameterName("result"), p2.ParameterName);
|
||||
Assert.AreEqual(ParameterDirection.Output, p2.Direction);
|
||||
Assert.AreEqual(DbType.Int32, p2.DbType);
|
||||
Assert.AreEqual(DBNull.Value, p2.Value);
|
||||
|
||||
Assert.AreEqual(Database.GetParameterName("description"), p3.ParameterName);
|
||||
Assert.AreEqual(ParameterDirection.InputOutput, p3.Direction);
|
||||
Assert.AreEqual(DbType.String, p3.DbType);
|
||||
Assert.AreEqual(256, p3.Size);
|
||||
Assert.AreEqual("seed", p3.Value);
|
||||
|
||||
Assert.AreEqual(0, result.ReturnParameters["status"]);
|
||||
Assert.AreEqual(2, result.ReturnParameters["result"]);
|
||||
Assert.AreEqual(3, result.ReturnParameters["description"]);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBindFallsBackToColumnAttributeMetadata()
|
||||
{
|
||||
using (IDbCommand cmd = new FakeDbCommand())
|
||||
{
|
||||
var result = DynamicProcedureParameterBinder.Bind(Database, cmd, new ProcedureParameterColumnFallbackObject
|
||||
{
|
||||
Code = "XYZ"
|
||||
});
|
||||
|
||||
Assert.IsFalse(result.ReturnValueAdded);
|
||||
Assert.IsNull(result.ReturnParameters);
|
||||
Assert.AreEqual(1, cmd.Parameters.Count);
|
||||
|
||||
var p0 = (IDbDataParameter)cmd.Parameters[0];
|
||||
Assert.AreEqual(Database.GetParameterName("code"), p0.ParameterName);
|
||||
Assert.AreEqual(ParameterDirection.Input, p0.Direction);
|
||||
Assert.AreEqual(DbType.String, p0.DbType);
|
||||
Assert.AreEqual(64, p0.Size);
|
||||
Assert.AreEqual("XYZ", p0.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user