【问题标题】:Table is nullable DateTime, but DataSet throws an exception?表可以为空DateTime,但DataSet抛出异常?
【发布时间】:2010-12-10 23:00:12
【问题描述】:

我正在尝试使用 DataSet 设计器从查询中创建数据表。我把这个记下来就好了。使用的查询从数据库返回一个可为空的日期时间列。但是,当涉及到这段代码时:

DataSet1.DataTable1DataTable table = adapter.GetData();

这会从以下位置引发 StrongTypingException:

[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public System.DateTime event_start_date {
    get {
        try {
            return ((global::System.DateTime)(this[this.tableDataTable1.event_start_dateColumn]));
        }
        catch (global::System.InvalidCastException e) {
            throw new global::System.Data.StrongTypingException("The value for column \'event_start_date\' in table \'DataTable1\' is DBNull.", e);
        }
    }
    set {
        this[this.tableDataTable1.event_start_dateColumn] = value;
    }
}

如何使用设计器让该列可以为 Nullable?

【问题讨论】:

    标签: c# dataset


    【解决方案1】:

    类型化数据集不支持可为空的类型。它们支持可为空的

    类型化数据集生成器创建不可为空的属性和相关方法来处理空值。如果创建DateTime 类型的MyDate 列并将AllowDbNull 设置为true,则DataRow 子类将实现名为MyDate 的不可为空的DateTime 属性、SetMyDateNull() 方法和IsMyDateNull() 方法。这意味着如果您想在代码中使用可为空的类型,您必须这样做:

    DateTime? myDateTime = myRow.IsMyDateNull() ? null : (DateTime?) row.MyDate;
    

    虽然这并没有完全违背使用类型化数据集的目的,但它确实很糟糕。例如,类型化数据集以一种不如System.Data 扩展方法可用的方式实现可空列,这令人沮丧。

    特别糟糕,因为类型化数据集确实在某些地方使用可空类型 - 例如,包含上述可空 DateTime 列的表的 Add<TableName>Row() 方法将采用 DateTime? 参数.

    很久以前,我在MSDN论坛上问过这个问题,最终ADO项目经理解释说,可空类型是与类型化数据集同时实现的,他的团队没有时间将两者完全整合.NET 2.0 的发货日期。据我所知,从那时起,他们就没有向类型化数据集添加新功能。

    【讨论】:

    • 在 .net 4.5 中仍然存在这个问题
    • 自 Visual Studio 2008 以来,已弃用类型化数据集以支持实体框架,因此,当 Microsoft 可以专注于 EF 时,不要指望他们会在这项技术上花费时间和精力。如果 Typed Datasets 缺乏对可空类型的支持对您来说是个大问题,我强烈建议您将项目迁移到 EF。
    • 改为迁移到 Dapper .NET。微软自己的 ORM 很臃肿。 NHibernate 应该也不错,但从未使用过。
    • 但是 EF 也充满了麻烦 - 上次我尝试使用它时,它一直在损坏。有时我对数据集感到非常沮丧,我只是使用强类型数据作为 datagridview 的数据源并处理我自己的更新和选择...
    • 不正确@Hoppe,DataSet 设计器会根据属性名称为您generate 这个方法。
    【解决方案2】:

    感谢这解决了我的类似问题:这是代码。 遇到这个问题

    Isevent_start_date()
    

    无论该字段是否为空,都会返回。

    就我而言:我遇到了类似的问题,我使用了以下解决方案

                //Table's Name is Efforts,
                //Column's name is Target
                //So the dataset would automatically generate a property called IsTargetNull() which can be used to check nullables
                //Create an Adaptor
                EffortsTableAdapter ad = new EffortsTableAdapter();
                ProjectDashBoard.Db.EffortsDataTable efforts = ad.GetData();
                DataColumn targetColumn = new DataColumn();
                targetColumn = efforts.TargetColumn;
    
                List<DateTime?> targetTime = new List<DateTime?>();
                foreach (var item in efforts)
                {
    
                    //----------------------------------------------------
                    //This is the line that we are discussing about : 
                    DateTime? myDateTime = item.IsTargetNull() ? null : (DateTime?)item.Target;
                    //----------------------------------------------------
    
                    targetTime.Add(myDateTime);
    
                }
    

    【讨论】:

      【解决方案3】:

      Designer 似乎获取了列的数据库类型错误。

      打开xsd Designer,点击F4 打开Properties Window。选择适当的列并将Nullable(或类似的,不记得确切名称)设置为true。

      【讨论】:

      • 是的,试过了。 AllowDBNull 设置为 true。 NullValue 属性只有以下选项:Empty、(Null) 和 Throw Exception。唯一允许设置的是 Throw Exception。
      • NullValue 属性是一条红鲱鱼;其目的是为空字符串提供值(您可以使用 codegen 属性为其他类型提供空默认值:rickyfaulstich.net/StichBLOG/archive/2003/12/05/194.aspx)。
      【解决方案4】:

      要使用 LINQ,您必须转到 dataset.xsd 中的 Tables 属性。首先查看并确保该列确实设置为可为空。那么您必须查看该列的特定属性“NullValue”。 Null Value 默认为“Exception”,至少在 VS 2012 中是这样。为 VB 将其设置为 Nothing,这样您就可以在 LINQ Where 子句中执行“IsNot Nothing”。

      【讨论】:

        【解决方案5】:

        我这样做是为了在 DateTime 列中插入值 NULL

        假设我在数据库中有一个nullable DateTime 列,我从数据库中检索了一个名为response 的对象中的一些数据,并且我想在名为RenewDate 的DataSet 列中插入nullable DateTime 值:

        // create anew row of the same type of your table row
        var rw = ds.StudentActionPrintDT.NewStudentActionPrintDTRow();
        
        // check for null value
        if(!response.RenewDate.HasValue)
        {
          // if null, then the let DataSet to set it null by it's own way 
          rw.SetRenewDateNull();
        }
        else
        {
          // if not null set value to the datetime value
          rw.RenewDate = response.RenewDate.Value;
        }
        // add the created row to the dateset [DataSetName].[ColumnName].Add[ColumnName]Row([The Created Row]);
        ds.StudentActionPrintDT.AddStudentActionPrintDTRow(rw);
        

        【讨论】:

          【解决方案6】:

          在数据集设计器中,使用System.Object数据类型而不是System.DateTime,并将NullValue设置为(Null),将DefaultValue设置为&lt;DBNull&gt;,并在需要时将其转换为:

          var row1 = dateSet1.table1.FirstOrDefault();
          if (row1 == null)
              return;
          DateTime? date = (DateTime?) row1.ObjectDate;
          

          【讨论】:

            【解决方案7】:

            我正在使用下面列出的代码来处理读取到数据表的 Excel 工作表中的空单元格。

            if (!reader.IsDBNull(0))                                
            {                                    
              row["DateOnCall"] = (DateTime)reader[0];
            }
            

            【讨论】:

              【解决方案8】:

              DataTable 和 Strongly Typed DataTable 似乎不同...这样使用。

              DataSet1.DataTable1DataTable table = new DataSet1.DataTable1DataTable();
              table.Merge(adapter.GetData().CopyToDataTable());
              

              【讨论】:

                【解决方案9】:

                System.DateTime 对象不可为空。要使 DateTime 可以为空,请将其设为 DateTime? (在 DateTime 之后放一个 ?)

                DateTime? nullableDateTime = null;
                

                【讨论】:

                • 是的,我知道这一点。数据集设计器不接受“日期时间?”然而,数据类型。
                • Nullable 类型不能与类型化数据集一起使用 - 设计使然
                • 无论如何要正确覆盖数据集的 .cs 文件?下次更新数据集时,.designer.cs 中任何列属性的更改都将被清除
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2016-07-07
                • 2010-12-09
                • 1970-01-01
                • 1970-01-01
                • 2012-02-09
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多