Reputation: 1264
In C# a DateTime property with value {27-01-2017 12.00.00 AM}
is being passed in a data table to a procedure with an UTT parameter. UTT also has the same datatype datetime. I am using the generic method provided below. I cannot explicitly convert data type.
Error : The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value. The data for table-valued parameter @UttParameter doesn't conform to the table type of the parameter.
SQL Server error is: 242, state: 3
The statement has been terminated.
public static DataTable ToDataTable<T>(IList<T> items, bool usePropertyMappingName = false)
{
DataTable dataTable = null;
if (items != null)
{
using (dataTable = new DataTable(typeof(T).Name))
{
dataTable.Locale = System.Globalization.CultureInfo.InvariantCulture;
// Get all the properties.
PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in props)
{
string columnName = prop.Name;
if (usePropertyMappingName)
{
var mappingAttribute = prop.GetCustomAttributes(typeof(PropertyMappingAttribute), true).FirstOrDefault() as PropertyMappingAttribute;
if (mappingAttribute != null && !string.IsNullOrEmpty(mappingAttribute.Name))
{
columnName = mappingAttribute.Name;
}
}
// Setting column names as Property names.
dataTable.Columns.Add(columnName, prop.PropertyType);
}
foreach (T item in items)
{
var values = new object[props.Length];
for (int i = 0; i < props.Length; i++)
{
// Inserting property values to data table rows.
values[i] = props[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
}
}
}
return dataTable;
}
Upvotes: 3
Views: 1109
Reputation: 67291
Your code - as it is now - will transfer any value on string level. This is a really bad approach. The implicit conversions taking place are highly depending on your system's settings (language and culture). The worst part is: This might work all great on your machine while you are testing it, but on a customer's system it breaks with strange messages. Happy Debugging :-(
Change your code like this
foreach (PropertyInfo prop in props) {
// Setting column names as Property names.
if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
dataTable.Columns.Add(prop.Name, prop.PropertyType.GetGenericArguments()[0]);
else
dataTable.Columns.Add(prop.Name, prop.PropertyType);
}
This will add the column - even if this is a nullable type - with the correct data type.
credits: This answer helped me
(thx to Yves M. in a comment below the linked answer)
foreach (PropertyInfo prop in props) {
// Setting column names as Property names.
dataTable.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
Upvotes: 1
Reputation: 543
You are using InvariantCulture as DataTable locale. Invariant culture expects Date to be in yyyy-MM-dd format.
Upvotes: 1