【问题标题】:DateTime nullable exception as a parameterDateTime 可空异常作为参数
【发布时间】:2009-05-08 19:15:49
【问题描述】:

我有一个搜索表单,可以按几个不同的字段进行搜索。问题字段是birthDate。在表单上它是一个字符串。在 SQL 2005 db 中,它是一个可以为空的 DateTime。

就在表单上声明变量然后设置它而言,下面的代码是连续的。然后调用 BLL,然后调用 DAL。

在这一行 -->

dgvSearchResults.DataSource =ConnectBLL.BLL.Person.Search(_firstName,_middleName,_lastName,_sSN, (DateTime)_birthDate,_applicationID,_applicationPersonID,_fuzzy);

我收到 “可空对象必须有值” 错误。

我假设是因为我没有提供 Date 参数,然后尝试将其转换为不可为空的 DateTime。对吗?

我能做些什么呢?必须有办法解决它。这完全相同的 BLL 和 DAL 也适用于网络应用版本。

编辑 1

有几点需要注意。我的印象是DateTime?Nullable<DateTime>是一样的,对吗?

另外,我不知道如何为 BirthDate 之类的字段输入任意值。我想我可以在我的业务层中构建一堆过滤器,但这似乎是“Hack”方式。也许不吧。此外,同样的 BLL 和 DAL 与同一个 DB 允许在该程序的 WebApp 版本的 BirthDate 字段中为空值,这让我感到困扰。有什么想法吗?对于那些没有日期的条目,数据库中有 null

Search.cs

public DateTime? _birthDate;
_birthDate = null;
if (datBirthDate.Text != string.Empty)
    _birthDate = Convert.ToDateTime(datBirthDate.Text);
dgvSearchResults.DataSource=ConnectBLL.BLL.Person.Search(_firstName,_middleName,_lastName,_sSN, (DateTime)_birthDate,_applicationID,_applicationPersonID,_fuzzy);

ConnectBLL --> Person.vb

Public Shared Function Search(ByVal firstName As String, ByVal middleName As String, ByVal lastName As String, ByVal SSN As String, ByVal birthDate As Date, ByVal applicationId As Integer, ByVal applicationPersonId As String, ByVal fuzzy As Boolean) As Data.DataTable
Try
    Dim tbl As Data.DataTable = DAL.Connect.SearchPerson(firstName, middleName, lastName, SSN, birthDate, applicationId, applicationPersonId, fuzzy)

    If tbl.Rows.Count > 0 Then
        tbl.DefaultView.Sort = "Last Name ASC, First Name ASC, Middle Name ASC"
    End If
    Return tbl
Catch
    Throw
End Try

结束函数

ConnectDAL --> Connect.vb

Public Shared Function SearchPerson(ByVal _FirstName As String, ByVal _MiddleName As String, ByVal _LastName As String, ByVal _SSN As String, ByVal _BirthDate As Date, ByVal _ApplicationID As Integer, ByVal _ApplicationPersonID As String, ByVal _Fuzzy As Boolean) As Data.DataTable
Dim test As New clsSqlResponseTime
Dim dt As New Data.DataTable
Try
    Using cnn As New SqlClient.SqlConnection(ConnectROConnectionString)
        Dim cmd As New SqlClient.SqlCommand()
        cmd.Connection = cnn
        If _Fuzzy Then
            cmd.CommandText = strSearchPersonFuzzyStoredProcedure
        Else
            cmd.CommandText = strSearchPersonStoredProcedure
        End If
        cmd.CommandType = CommandType.StoredProcedure
        If Not IsNothing(_FirstName) Then cmd.Parameters.Add(New SqlClient.SqlParameter("@FirstName", _FirstName))
        If Not IsNothing(_MiddleName) Then cmd.Parameters.Add(New SqlClient.SqlParameter("@MiddleName", _MiddleName))
        If Not IsNothing(_LastName) Then cmd.Parameters.Add(New SqlClient.SqlParameter("@LastName", _LastName))
        If Not IsNothing(_SSN) Then cmd.Parameters.Add(New SqlClient.SqlParameter("@SSN", _SSN))
        If Not (_BirthDate = Date.MinValue) Then cmd.Parameters.Add(New SqlClient.SqlParameter("@BirthDate", _BirthDate))
        If Not IsNothing(_ApplicationPersonID) Then cmd.Parameters.Add(New SqlClient.SqlParameter("@ApplicationID", _ApplicationID))
        If Not IsNothing(_ApplicationPersonID) Then cmd.Parameters.Add(New SqlClient.SqlParameter("@ApplicationPersonID", _ApplicationPersonID))

        Dim da As New SqlClient.SqlDataAdapter(cmd)
        da.Fill(dt)
    End Using
Catch
    Throw
End Try
test.Log("SearchPerson", "Connect")
Return dt

结束函数

【问题讨论】:

    标签: c# vb.net winforms parameters null


    【解决方案1】:

    在我看来,在第三个函数被添加到参数集合之前,您根本没有使用birthDate 值。在第三个函数中,它在添加之前已经针对 Date.MinValue 进行了测试。只需将第一个函数更改为:

    public DateTime _birthDate;
    if (string.IsNullOrEmpty(datBirthDate.Text))
        _birthDate = DateTime.MinValue;
    else
        _birthDate = Convert.ToDateTime(datBirthDate.Text);
    dgvSearchResults.DataSource=ConnectBLL.BLL.Person.Search(_firstName,_middleName,_lastName,_sSN,_birthDate,_applicationID,_applicationPersonID,_fuzzy);
    

    这是最简单的出路,但不一定是最正确的。我会更改所有三个函数以使用 Nullable DateTime,如下所示:

    功能 1

    public DateTime? _birthDate = null;
    if (!string.IsNullOrEmpty(datBirthDate.Text))
        _birthDate = Convert.ToDateTime(datBirthDate.Text);
    dgvSearchResults.DataSource=ConnectBLL.BLL.Person.Search(_firstName,_middleName,_lastName,_sSN,_birthDate,_applicationID,_applicationPersonID,_fuzzy);
    

    函数 2 和 3 的定义应如下所示:

    Public Shared Function Search(ByVal firstName As String, ByVal middleName As String, ByVal lastName As String, ByVal SSN As String, ByVal birthDate As Nullable(Of Date), ByVal applicationId As Integer, ByVal applicationPersonId As String, ByVal fuzzy As Boolean) As Data.DataTable
    
    Public Shared Function SearchPerson(ByVal _FirstName As String, ByVal _MiddleName As String, ByVal _LastName As String, ByVal _SSN As String, ByVal _BirthDate As Nullable(Of Date), ByVal _ApplicationID As Integer, ByVal _ApplicationPersonID As String, ByVal _Fuzzy As Boolean) As Data.DataTable
    

    函数 3 中使用birthDate 的行:

    If (_BirthDate.HasValue) Then cmd.Parameters.Add(New SqlClient.SqlParameter("@BirthDate", _BirthDate.Value))
    

    【讨论】:

    • 是的,您的第一个函数当前将 _birthDate 定义为 Nullable DateTime。但是您并没有通过将其显式转换回 DateTime 来正确对待它。如果您需要来自可为空的基础 DateTime,请首先检查 HasValue 属性,然后使用 Value 属性获取 DateTime。请注意,如果 HasValue 为 false,Value 将抛出 InvalidOperationException。
    • 谢谢。我仍然对为什么这在 Web 应用程序中不是问题感到困惑,但这帮助我获得了我的 WinForm 版本。谢谢!
    【解决方案2】:

    你可以这样做:

    dgvSearchResults.DataSource=ConnectBLL.BLL.Person.Search(_firstName,_middleName,_lastName,_sSN, _birthDate.HasValue ? _birthDate.Value : new DateTime() ,_applicationID,_applicationPersonID,_fuzzy);
    

    基本上,如果它为空,只需将其默认为 DateTime 的默认值(我相信它是 1/1/0001)。

    【讨论】:

    • 我尝试了类似的方法,但 1/1/0001 与 SQL 的默认值不兼容。
    【解决方案3】:

    您看起来正试图在此行的 Search.cs 中将可能的 Null 值强制转换为 DateTime。

    dgvSearchResults.DataSource=ConnectBLL.BLL.Person.Search(_firstName,_middleName,_lastName,_sSN, (DateTime)_birthDate,_applicationID,_applicationPersonID,_fuzzy);

    这将导致此错误。如果字符串为空,您会将 null 强制转换为 DateTime,这会爆炸。我建议您的 Person.Search 方法将 Nullable 作为参数并在那里处理 null 情况或将其设置为 DateTime.MinValue 并在 Person.Search 中将其视为 null。

    【讨论】:

      【解决方案4】:

      为什么不将 _birthDate 设置为 null,为什么不设置一些 DateTime 值呢?这样它就不能为 null 传递给 BLL 调用。 DateTime.MinValue 或 DateTime.Now 都可以工作。

      【讨论】:

      • 那我不会有数据完整性问题吗?给人们无效的生日?
      猜你喜欢
      • 1970-01-01
      • 2010-12-10
      • 2021-08-22
      • 1970-01-01
      • 1970-01-01
      • 2013-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多