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”的整数索引