Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用SQLDataReader的可空DateTime_C#_Asp.net - Fatal编程技术网

C# 使用SQLDataReader的可空DateTime

C# 使用SQLDataReader的可空DateTime,c#,asp.net,C#,Asp.net,我几乎不喜欢问这个问题,好像它已经被问了一百万次了,但即使我研究了另一个问题,在我的案例中,我似乎仍然无法解决这个问题 我读到DateTime是一种可为NULL的类型,我尝试了一些示例,但我正在尝试找出我的SQLDATAREADER失败的数据库中DateTime是否为NULL 错误 System.Data.SqlTypes.SqlNullValueException:数据为空。无法“对空值调用”此方法或属性 详细信息类 private DateTime? startingDate; publi

我几乎不喜欢问这个问题,好像它已经被问了一百万次了,但即使我研究了另一个问题,在我的案例中,我似乎仍然无法解决这个问题


我读到DateTime是一种可为NULL的类型,我尝试了一些示例,但我正在尝试找出我的SQLDATAREADER失败的数据库中DateTime是否为NULL

错误

System.Data.SqlTypes.SqlNullValueException:数据为空。无法“对空值调用”此方法或属性

详细信息类

private DateTime? startingDate;

public DateTime? StartingDate
{
    get{ return startingDate; }
    set{ startingDate = value; }
}

// constructor
Public DetailsClass(DateTime? startingDate)
{
    this.startingDate = startingDate;
}
   using (SqlConnection con = new SqlConnection(connectionString))
            using (SqlCommand cmd = con.CreateCommand())
            {

                List<DetailsClass> details = new List<DetailsClass>();
                DetailsClass dtl;
                try
                {
                    con.Open();
                    cmd.CommandText = "Stored Procedure Name";
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@MyParameter", myparameter);

                    using (SqlDataReader reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            dtl = new DetailsClass((
                                reader.GetInt32(reader.GetOrdinal("MEMBERSHIPGEN"))),
                                reader.IsDBNull(1) ? null : reader.GetString(reader.GetOrdinal("EMAIL")),
                                reader.GetDateTime(reader.GetOrdinal("STARTINGDATE")));


                            details.Add(dtl);
                        }
                        reader.Close();
                        return details;

                    }
                }
DBClass

private DateTime? startingDate;

public DateTime? StartingDate
{
    get{ return startingDate; }
    set{ startingDate = value; }
}

// constructor
Public DetailsClass(DateTime? startingDate)
{
    this.startingDate = startingDate;
}
   using (SqlConnection con = new SqlConnection(connectionString))
            using (SqlCommand cmd = con.CreateCommand())
            {

                List<DetailsClass> details = new List<DetailsClass>();
                DetailsClass dtl;
                try
                {
                    con.Open();
                    cmd.CommandText = "Stored Procedure Name";
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@MyParameter", myparameter);

                    using (SqlDataReader reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            dtl = new DetailsClass((
                                reader.GetInt32(reader.GetOrdinal("MEMBERSHIPGEN"))),
                                reader.IsDBNull(1) ? null : reader.GetString(reader.GetOrdinal("EMAIL")),
                                reader.GetDateTime(reader.GetOrdinal("STARTINGDATE")));


                            details.Add(dtl);
                        }
                        reader.Close();
                        return details;

                    }
                }
使用(SqlConnection con=newsqlconnection(connectionString))
使用(SqlCommand cmd=con.CreateCommand())
{
列表详细信息=新列表();
细节类dtl;
尝试
{
con.Open();
cmd.CommandText=“存储过程名称”;
cmd.CommandType=CommandType.storedProcess;
cmd.Parameters.AddWithValue(“@MyParameter”,MyParameter);
使用(SqlDataReader=cmd.ExecuteReader())
{
while(reader.Read())
{
dtl=新的详细信息类((
reader.GetInt32(reader.GetOrdinal(“MEMBERSHIPGEN”),
reader.IsDBNull(1)?null:reader.GetString(reader.GetOrdinal(“电子邮件”)),
reader.GetDateTime(reader.GetOrdinal(“开始日期”));
详细信息。添加(dtl);
}
reader.Close();
退货详情;
}
}
更换

DateTime startingDate;

问号将其标记为可为null的值,您的读者应该能够将startingdate设置为null,而不是引发异常

您还可以在读卡器工作时检查空值,并用空字符串替换空值

while(reader.read())
{
  //column is an int value of your column. I.e: if the column ist the 8th column, set column to 7 (0-based)
  StartingDate = (reader.IsDBNull(column)) ? null : reader.GetOrdinal("STARTINGDATE"));
 //instead of null you could also return a specific date like 1.1.1900 or String.Empty
}
试试这个:

startingDate
变量
设为可空
,如下所示:

DateTime? startingDate;
if !reader.IsDBNull(reader.GetOrdinal("STARTINGDATE"))
{
    startingDate = reader.GetDateTime(reader.GetOrdinal("STARTINGDATE"));
}
else
{
    startingDate = null;
}
现在,从
SqlDataReader
对象检索值时,需要使用
IsDbNull
方法,该方法将确定从数据库返回的值是否为
NULL
,如下所示:

DateTime? startingDate;
if !reader.IsDBNull(reader.GetOrdinal("STARTINGDATE"))
{
    startingDate = reader.GetDateTime(reader.GetOrdinal("STARTINGDATE"));
}
else
{
    startingDate = null;
}

注意:我不确定您将从数据库读取的值分配到哪里,因为它没有显示在发布的代码中。这就是我在示例中直接分配它的原因,但您可能需要调整示例逻辑的位置。

这里有一个从读卡器中获取值的辅助方法

public static class ReaderExtensions {

  public static DateTime? GetNullableDateTime(this SqlDataReader reader, string name){ 
       var col = reader.GetOrdinal(name);
       return reader.IsDBNull(col) ? 
                   (DateTime?)null :
                   (DateTime?)reader.GetDateTime(col);
  }
}
如何使用以回应评论的更新

using (SqlConnection con = new SqlConnection(connectionString))
        using (SqlCommand cmd = con.CreateCommand())
        {

            List<DetailsClass> details = new List<DetailsClass>();
            DetailsClass dtl;
            try
            {
                con.Open();
                cmd.CommandText = "Stored Procedure Name";
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@MyParameter", myparameter);

                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        dtl = new DetailsClass((
                            reader.GetInt32(reader.GetOrdinal("MEMBERSHIPGEN"))),
                            reader.IsDBNull(1) ? null : reader.GetString(reader.GetOrdinal("EMAIL")),
                            reader.GetNullableDateTime("STARTINGDATE"));


                        details.Add(dtl);
                    }
                    reader.Close();
                    return details;

                }
            }
使用(SqlConnection con=newsqlconnection(connectionString))
使用(SqlCommand cmd=con.CreateCommand())
{
列表详细信息=新列表();
细节类dtl;
尝试
{
con.Open();
cmd.CommandText=“存储过程名称”;
cmd.CommandType=CommandType.storedProcess;
cmd.Parameters.AddWithValue(“@MyParameter”,MyParameter);
使用(SqlDataReader=cmd.ExecuteReader())
{
while(reader.Read())
{
dtl=新的详细信息类((
reader.GetInt32(reader.GetOrdinal(“MEMBERSHIPGEN”),
reader.IsDBNull(1)?null:reader.GetString(reader.GetOrdinal(“电子邮件”)),
reader.GetNullableDateTime(“STARTINGDATE”);
详细信息。添加(dtl);
}
reader.Close();
退货详情;
}
}

另请注意,您使用的是
reader.IsDBNull(1)
,然后是
reader.GetOrdinal
。可能应该是
reader.IsDBNull(reader.GetOrdinal(“EMAIL”)

,您能告诉我们调试时哪一行抛出了错误吗?这样会更容易些

if (! reader.IsDBNull(reader.GetOrdinal("STARTINGDATE"))) {
    obj.startingDate = reader.GetDateTime(reader.GetOrdinal("STARTINGDATE"));
}
如果它是DBNull,则无需显式分配null,因为它是一个可为null的类型,所以默认情况下它将包含null

好的,根据您更新的代码(注意注释):

让我们以更详细的方式进行尝试:

while (reader.Read()) {

    dtl = new DetailsClass();

    dtl.membershipgen = reader.IsDBNull(reader.GetOrdinal("MEMBERSHIPGEN")) ? null : reader.GetInt32(reader.GetOrdinal("MEMBERSHIPGEN"));
    dtl.email = reader.IsDBNull(reader.GetOrdinal("EMAIL")) ? null : reader.GetString(reader.GetOrdinal("EMAIL")),
    dtl.startingdate = reader.IsDBNull(reader.GetOrdinal("STARTINGDATE")) ? null : reader.GetDateTime(reader.GetOrdinal("STARTINGDATE")));

    details.Add(dtl);
}

我知道这个问题已经得到了回答,但进一步简化了处理其他可为null的变量类型的代码。上面的答案仅限于一种特定的变量类型。好处是它还允许您包含默认值,而不是将其设置为null

public static T GetDataType<T>( this SqlDataReader r, string name, object def = null )
{
     var col = r.GetOrdinal(name);
     return r.IsDBNull(col) ? (T)def : (T)r[name];
}
publicstatict GetDataType(此SqlDataReader r,字符串名,对象def=null)
{
var col=r.GetOrdinal(名称);
返回r.IsDBNull(col)?(T)def:(T)r[名称];
}
然后在代码中,您可以使用

...
while(reader.Read())
{
    data1Bool = reader.GetDataType<bool?>("data1"); // if it's null then we'll set it as null
    data2intNotNull = reader.GetDataType<int>("data2", 0); // if the data is null, then we'll set to 0
    data3date = reader.GetDataType<DateTime?>("data3", DateTime.Now); // same example as above, but instead of setting to 0, I can default it to today's date.
}
...
。。。
while(reader.Read())
{
data1Bool=reader.GetDataType(“data1”);//如果为null,则将其设置为null
data2intNotNull=reader.GetDataType(“data2”,0);//如果数据为null,那么我们将设置为0
data3date=reader.GetDataType(“data3”,DateTime.Now);//与上面的示例相同,但我可以将其默认为今天的日期,而不是设置为0。
}
...

关于可为null的值对象,我遇到了其他问题,这节省了我数小时的时间试图弄清楚发生了什么。(WPF在编译运行时时没有解释这个问题。)

“我了解到DateTime是可为null的类型”-你读错了。
DateTime
不可为空,
DateTime?
是。我理解你现在说的话,我只是留下了问号。我根据你的建议编辑了我的代码,但仍然抛出相同的错误。我知道是这个字段导致了错误,当我在数据库中放置一个值时,它填充得很好。这de错误:reader.GetOrdinal获取命名字段“STA”的整数索引