“Specified cast is not valid” in LINQ when DateTime field is null

后端 未结 2 581
走了就别回头了
走了就别回头了 2021-01-23 19:59

I got a problem. This my code use a LINQ.

var resultCases = from row2 in dtCases.AsEnumerable()
                  where row2.Field(\"caseID\") == case         


        
相关标签:
2条回答
  • 2021-01-23 20:45

    Update: try this

    public static class ConversionExtensions
    {
        public static string SafeDateTime(this object value)
        {
            if (value == DBNull.Value) return string.Empty;
    
            var valueType = value.GetType();
            if (typeof (DateTime?).IsAssignableFrom(valueType))
            {
                var nullableValue = value as DateTime?;
                if (nullableValue == null) return string.Empty;
                return nullableValue.Value.ToString();
            }
            if (typeof (DateTime).IsAssignableFrom(valueType))
            {
                return ((DateTime) value).ToString();
            }
            return string.Empty;
        }
    }
    

    Called with:

    effectiveDate = row2["caseEffectiveDate"].SafeDateTime()
    
    0 讨论(0)
  • 2021-01-23 20:50

    tldr; The issue is two-fold: DataTable uses DBNull.Value to represent "null" values and neither DBNull.Value or null are castable to DateTime.

    The Field<T> extension method was added later to make dealing with DBNull and Nullable/reference types with null values much easier; it also hides the conversion behind a strongly-typed signature. These LINQ to DataSet extension method knows how to map DBNull.Value to null as appropriate.

    Because of this using row.Field<DateTime?>("caseEffectiveDate") will return either the DateTime? with a value (if the query returned a value) or null, and it may also throw an exception if the server returned an incompatible value - but it will never return DBNull.Value.

    However, the standard row["caseEffectiveDate"] will return a DateTime value (or some other type) or DBValue.Null which is not cast-able to DateTime? (much less a DateTime) and results in the error described.

    Here is how to minimally reproduce this exception:

    object v = DBNull.Value;
    DateTime dt = (DateTime)v;
    

    However, it is fine to convert a null to a DateTime?:

    object v = null;
    DateTime? maybeDt = (DateTime?)v;
    

    And then trivial to coalesce it away to DateTime if required:

    object v = null;
    DateTime? dt = (DateTime?)v ?? DateTime.MinValue;
    
    0 讨论(0)
提交回复
热议问题