diff --git a/src/AdoNetCore.AseClient/AseCommandBuilder.cs b/src/AdoNetCore.AseClient/AseCommandBuilder.cs
index 32ef1c0..63490a6 100644
--- a/src/AdoNetCore.AseClient/AseCommandBuilder.cs
+++ b/src/AdoNetCore.AseClient/AseCommandBuilder.cs
@@ -224,12 +224,15 @@ private static DataTable GetSchemaTableWithKeyInfo(DbCommand sourceCommand)
if (dataTable != null)
{
// If there is no primary key on the table, then throw MissingPrimaryKeyException.
- var isKeyColumn = dataTable.Columns["IsKey"];
+ var isKeyColumn = dataTable.Columns[SchemaTableColumn.IsKey];
+ var isUniqueColumn = dataTable.Columns[SchemaTableColumn.IsUnique];
+
var hasKey = false;
foreach (DataRow columnDescriptorRow in dataTable.Rows)
{
- hasKey |= (bool)columnDescriptorRow[isKeyColumn];
+ hasKey |= (bool)columnDescriptorRow[isKeyColumn] ||
+ (bool)columnDescriptorRow[isUniqueColumn];
if (hasKey)
{
diff --git a/src/AdoNetCore.AseClient/AseParameterCollection.cs b/src/AdoNetCore.AseClient/AseParameterCollection.cs
index 5027c13..fdd7ad1 100644
--- a/src/AdoNetCore.AseClient/AseParameterCollection.cs
+++ b/src/AdoNetCore.AseClient/AseParameterCollection.cs
@@ -263,10 +263,10 @@ public AseParameter Add(string parameterName, AseDbType dbType, int size, Parame
/// A new object.
public AseParameter Add(AseParameter parameter)
{
- if (parameter != null)
- {
- _parameters.Add(parameter);
- }
+ if (parameter == null) throw new ArgumentNullException(nameof(parameter));
+ if (Contains(parameter)) throw new ArgumentException($"parameter name '{parameter.ParameterName}' is already in the collection");
+
+ _parameters.Add(parameter);
return parameter;
}
@@ -379,6 +379,7 @@ public override int Add(object value)
{
if (value is AseParameter p)
{
+ if (Contains(p)) throw new ArgumentException($"Parameter name: '{p.ParameterName}' is already registered", nameof(value));
return ((IList)_parameters).Add(p);
}
return -1;
@@ -438,15 +439,23 @@ public override int IndexOf(object value)
/// Returns -1 when the object does not exist in the .
public int IndexOf(AseParameter value)
{
- if (value != null)
+ if (value == null) return -1;
+ for (var i = 0; i < _parameters.Count; i++)
{
- for (var i = 0; i < _parameters.Count; i++)
+ if (string.IsNullOrWhiteSpace(value.ParameterName))
{
if (value == _parameters[i])
{
return i;
}
}
+ else
+ {
+ if (value == _parameters[i] || value.ParameterName == _parameters[i].ParameterName)
+ {
+ return i;
+ }
+ }
}
return -1;
@@ -459,6 +468,7 @@ public int IndexOf(AseParameter value)
/// The object to add to the collection.
public override void Insert(int index, object parameter)
{
+ if (Contains(parameter)) throw new ArgumentException($"parameter name '{parameter}' is already in the collection");
((IList)_parameters).Insert(index, parameter);
}
@@ -469,6 +479,7 @@ public override void Insert(int index, object parameter)
/// The object to add to the collection.
public void Insert(int index, AseParameter parameter)
{
+ if (Contains(parameter)) throw new ArgumentException($"parameter name '{parameter.ParameterName}' is already in the collection");
((IList)_parameters).Insert(index, parameter);
}
@@ -521,10 +532,7 @@ public override void RemoveAt(int index)
/// The starting index of the array.
public override void CopyTo(Array array, int index)
{
- if (array != null)
- {
- ((IList)_parameters).CopyTo(array, index);
- }
+ ((IList)_parameters).CopyTo(array, index);
}
///
diff --git a/src/AdoNetCore.AseClient/Internal/FormatItem.cs b/src/AdoNetCore.AseClient/Internal/FormatItem.cs
index d0b5a20..40f994d 100644
--- a/src/AdoNetCore.AseClient/Internal/FormatItem.cs
+++ b/src/AdoNetCore.AseClient/Internal/FormatItem.cs
@@ -66,11 +66,11 @@ public string ParameterName
public static FormatItem CreateForParameter(AseParameter parameter, DbEnvironment env, AseCommand command)
{
+ parameter.AseDbType = TypeMap.InferType(parameter);
+
var dbType = parameter.DbType;
var length = TypeMap.GetFormatLength(dbType, parameter, env.Encoding);
- parameter.AseDbType = TypeMap.InferType(parameter);
-
var format = command.FormatItem;
var parameterName = parameter.ParameterName ?? command.Parameters.IndexOf(parameter).ToString();
if (!(command.FormatItem != null && command.FormatItem.ParameterName == parameterName &&
diff --git a/src/AdoNetCore.AseClient/Internal/SchemaTableBuilder.cs b/src/AdoNetCore.AseClient/Internal/SchemaTableBuilder.cs
index 29b88a0..6298f58 100644
--- a/src/AdoNetCore.AseClient/Internal/SchemaTableBuilder.cs
+++ b/src/AdoNetCore.AseClient/Internal/SchemaTableBuilder.cs
@@ -130,17 +130,12 @@ private FillTableResults FillTableFromFormats(DataTable table)
private void TryLoadKeyInfo(DataTable table, string baseTableNameValue, string baseSchemaNameValue, string baseCatalogNameValue)
{
if (_connection == null)
- {
throw new InvalidOperationException("Invalid AseCommand.Connection");
- }
if (_connection.State != ConnectionState.Open)
- {
throw new InvalidOperationException("Invalid AseCommand.Connection.ConnectionState");
- }
- if (!string.IsNullOrWhiteSpace(baseTableNameValue) &&
- !string.IsNullOrWhiteSpace(baseCatalogNameValue))
+ if (string.IsNullOrWhiteSpace(baseTableNameValue))
return;
using (var command = _connection.CreateCommand())
diff --git a/test/AdoNetCore.AseClient.Tests/Integration/AseCommandTests.cs b/test/AdoNetCore.AseClient.Tests/Integration/AseCommandTests.cs
index 0ffdac3..83888ba 100644
--- a/test/AdoNetCore.AseClient.Tests/Integration/AseCommandTests.cs
+++ b/test/AdoNetCore.AseClient.Tests/Integration/AseCommandTests.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Data;
using System.Xml;
using AdoNetCore.AseClient.Internal;
using AdoNetCore.AseClient.Tests.Util;
@@ -236,28 +237,45 @@ public void Command_Reuse_ShouldWork_For_NonNull_Value(System.Data.DbType dbType
}
}
}
+
+ [Test]
+ public void Command_Duplicate_Parameter_Name_Should_Throws_ArgumentException()
+ {
+ using (var connection = GetConnection())
+ {
+ connection.Open();
+ var sql = "select @p1, @p2";
+ var aseCommand = connection.CreateCommand();
+ aseCommand.CommandText = sql;
+ aseCommand.CommandType = CommandType.Text;
+ aseCommand.Parameters.Add("@p1", "test");
+ aseCommand.Parameters.Add("@p2", "test2");
+ Assert.Throws(() => aseCommand.Parameters.Add("@p1", "test3"));
+ }
+ }
+
private static IEnumerable ReUseCommandTypeData()
{
- yield return new TestCaseData(System.Data.DbType.Boolean, typeof(bool), false);
- yield return new TestCaseData(System.Data.DbType.Byte, typeof(byte), 12);
- yield return new TestCaseData(System.Data.DbType.SByte, typeof(sbyte), 2);
- yield return new TestCaseData(System.Data.DbType.Int16, typeof(short), 3);
- yield return new TestCaseData(System.Data.DbType.UInt16, typeof(ushort), 4);
- yield return new TestCaseData(System.Data.DbType.Int32, typeof(int), 23);
- yield return new TestCaseData(System.Data.DbType.UInt32, typeof(uint), 45);
- yield return new TestCaseData(System.Data.DbType.Int64, typeof(long), 76434755);
- yield return new TestCaseData(System.Data.DbType.UInt64, typeof(ulong), 1223);
- yield return new TestCaseData(System.Data.DbType.String, typeof(string), "If it could only be like this always—always summer, always alone, the fruit always ripe");
- yield return new TestCaseData(System.Data.DbType.AnsiString, typeof(string), "Doubt thou the stars are fire; Doubt that the sun doth move; Doubt truth to be a liar; But never doubt I love");
- yield return new TestCaseData(System.Data.DbType.AnsiStringFixedLength, typeof(string), "For never was a story of more woe than this of Juliet and her Romeo.");
- yield return new TestCaseData(System.Data.DbType.Guid, typeof(string), "e2207b47-3fce-4187-808f-e206398a9133");
- yield return new TestCaseData(System.Data.DbType.Decimal, typeof(decimal), 342.23);
- yield return new TestCaseData(System.Data.DbType.Currency, typeof(decimal), 1233.3);
- yield return new TestCaseData(System.Data.DbType.Single, typeof(float), 20.34f);
- yield return new TestCaseData(System.Data.DbType.Double, typeof(double), 3423.234d);
- yield return new TestCaseData(System.Data.DbType.DateTime, typeof(DateTime), "2019-03-13 03:20:35.23 AM");
- yield return new TestCaseData(System.Data.DbType.Date, typeof(DateTime), "2018-07-04 23:20:35.23 PM");
- yield return new TestCaseData(System.Data.DbType.Time, typeof(DateTime), "2014-09-10 23:20:35");
+ yield return new TestCaseData(DbType.Boolean, typeof(bool), false);
+ yield return new TestCaseData(DbType.Byte, typeof(byte), 12);
+ yield return new TestCaseData(DbType.SByte, typeof(sbyte), 2);
+ yield return new TestCaseData(DbType.Int16, typeof(short), 3);
+ yield return new TestCaseData(DbType.UInt16, typeof(ushort), 4);
+ yield return new TestCaseData(DbType.Int32, typeof(int), 23);
+ yield return new TestCaseData(DbType.UInt32, typeof(uint), 45);
+ yield return new TestCaseData(DbType.Int64, typeof(long), 76434755);
+ yield return new TestCaseData(DbType.UInt64, typeof(ulong), 1223);
+ yield return new TestCaseData(DbType.String, typeof(string), "If it could only be like this always—always summer, always alone, the fruit always ripe");
+ yield return new TestCaseData(DbType.AnsiString, typeof(string), "Doubt thou the stars are fire; Doubt that the sun doth move; Doubt truth to be a liar; But never doubt I love");
+ yield return new TestCaseData(DbType.AnsiStringFixedLength, typeof(string), "For never was a story of more woe than this of Juliet and her Romeo.");
+ yield return new TestCaseData(DbType.Guid, typeof(string), "e2207b47-3fce-4187-808f-e206398a9133");
+ yield return new TestCaseData(DbType.Decimal, typeof(decimal), 342.23);
+ yield return new TestCaseData(DbType.Currency, typeof(decimal), 1233.3);
+ yield return new TestCaseData(DbType.Single, typeof(float), 20.34f);
+ yield return new TestCaseData(DbType.Double, typeof(double), 3423.234d);
+ yield return new TestCaseData(DbType.DateTime, typeof(DateTime), "2019-03-13 03:20:35.23 AM");
+ yield return new TestCaseData(DbType.Date, typeof(DateTime), "2018-07-04 23:20:35.23 PM");
+ yield return new TestCaseData(DbType.Time, typeof(DateTime), "2014-09-10 23:20:35");
}