views:

519

answers:

1

I need to get the minimum DateTime value of a column in a DataTable. The DataTable is generated dynamically from a CSV file, therefore I don't know the name of that column until runtime. Here is code I've got that doesn't work...

private DateTime GetStartDateFromCSV(string inputFile, string date_attr)
{
    EnumerableRowCollection<DataRow> table = CsvStreamReader.GetDataTableFromCSV(inputFile, "input", true).AsEnumerable();
    DateTime dt = table.Select(record => record.Field<DateTime>(date_attr)).Min();
    return dt;
}

The variable table is broken out just for clarity. I basically need to find the minimum value as a DateTime for one of the columns (to be chosen at runtime and represented by date_attr).

I have tried several solutions from SO (most deal with known columns and/or non-DateTime fields). What I've got throws an error at runtime telling me that it can't do the DateTime conversion (that seems to be a problem with Linq?)

I've confirmed that the data for the column name that is in the string date_attr is a date value.

UPDATE: Stacktrace as requested:

System.InvalidCastException was unhandled by user code
  Message="Specified cast is not valid."
  Source="System.Data.DataSetExtensions"
  StackTrace:
       at System.Data.DataRowExtensions.UnboxT`1.ValueField(Object value)
       at System.Data.DataRowExtensions.Field[T](DataRow row, String columnName)
       at Presenter.Views.NetworkVisualizationDetailPresenter.<>c__DisplayClass1.<GetStartDateFromCSV>b__0(DataRow t) in Presenter\Views\NetworkVisualizationDetailPresenter.cs:line 194
       at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
       at System.Linq.Enumerable.Min[TSource](IEnumerable`1 source)
       at System.Linq.Enumerable.Min[TSource,TResult](IEnumerable`1 source, Func`2 selector)
       atPresenter.Views.NetworkVisualizationDetailPresenter.GetStartDateFromCSV(String inputFile, String date_attr) in Presenter\Views\NetworkVisualizationDetailPresenter.cs:line 194
       at Presenter.Views.NetworkVisualizationDetailPresenter.GetDynamicNetworkVisualizationData(String inputFile, Int32 dataMode, Int32 timeInterval, String date_attr, String entity_attr, String event_attr) in Views\NetworkVisualizationDetailPresenter.cs:line 123
       at Presenter.Views.NetworkVisualizationDetail.Page_Load(Object sender, EventArgs e) in NetworkVisualizationDetail.aspx.cs:line 114
       at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
       at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
       at System.Web.UI.Control.OnLoad(EventArgs e)
       at System.Web.UI.Control.LoadRecursive()
       at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
  InnerException: 
+1  A: 

Actually it seems like your problem is not in Linq, but in the data in your data table. If your error states that is can't do the DateTime conversion, your error most likely is generated here:

record.Field<DateTime>(date_attr)

which isn't in Linq.

Check that all of your rows have the correct value in this column. Also, if you could dump your stack trace from the exception it would help..

UPD: Looking at the stack trace update, I can see the top 2 entries in it:

at System.Data.DataRowExtensions.UnboxT`1.ValueField(Object value)
at System.Data.DataRowExtensions.Field[T](DataRow row, String columnName)

This most definitely confirms that the problem is not inside linq, but in the actual data that you're trying to convert. Second call is the exception message, definitely a data conversion problem:

Message="Specified cast is not valid."

I have just double checked, this code would work on a datatable, if the column type were DateTime.

table.Select(record => record.Field<DateTime>(date_attr)).Min();

But if the column type is string - it throws the exception you're getting, with the same stack trace! :)

Change it to this, and you shouldn't get any errors (that is considering your data is valid):

table.Select(record => Convert.ToDateTime(record[date_attr])).Min();
Artiom Chilaru
If I look here -> http://msdn.microsoft.com/en-us/library/system.linq.enumerable.min.aspx I see that DateTime is not one of the types supported for the MIN() method on Enumerable. Is this the problem?
Jay Stevens
@Jay no, that's not the case.. I can definitely confirm that .NET Min supports the DateTime type.
Artiom Chilaru
ok. This may be my misunderstanding (I'm relatively new to C#); I thought that the <DateTime> cast was going to do the conversion from string to datetime for me...
Jay Stevens
FRAKKIN' A!!! Artiom is my new hero. Thanks man, WORKS PERFECTLY!!duh.
Jay Stevens
Nope, in this case it was trying to do the direct cast instead of conversion - hence your error :)Good luck! )
Artiom Chilaru
hehe, I have a fan ^_^Thanks!
Artiom Chilaru