3

我正在使用 C# 和 SQL Server 使用 ASP.NET MVC 4

我正在从下表中选择一行数据

CREATE TABLE [dbo].[Mem_Basic] (
[Id]          INT           IDENTITY (1, 1) NOT NULL,
[Mem_NA]      VARCHAR (100) NOT NULL,
[Mem_Occ]     VARCHAR (200) NOT NULL,
[Mem_Role]    VARCHAR (200) NOT NULL,
[Mem_Email]   VARCHAR (50)  NULL,
[Mem_MPh]     VARCHAR (15)  NULL,
[Mem_DOB]     DATE          NULL,
[Mem_BGr]     NCHAR (10)    NULL,
[Mem_WAnn]    DATE          NULL,
[Mem_Spouse]  VARCHAR (75)  NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);

使用以下代码

public MemberBasicData GetMemberProfile(int id)
{
        MemberBasicData mb = new MemberBasicData();
        using (SqlConnection con = new SqlConnection(Config.ConnectionString))
        {
            using (SqlCommand cmd = new SqlCommand("SELECT * FROM Mem_Basic WHERE Id="+id+"", con))
            {
                try
                {
                    con.Open();
                    SqlDataReader reader = cmd.ExecuteReader();
                   if(reader.Read()==true)
                    {
                        mb.Id = (int)reader["Id"];
                        mb.Mem_NA = (string)reader["Mem_NA"];
                        mb.Mem_Occ = (string)reader["Mem_Occ"];
                        mb.Mem_Role = (string)reader["Mem_Role"];
                        mb.Mem_Email = (string)reader["Mem_Email"];
                        mb.Mem_MPh = (string)reader["Mem_MPh"];
                        mb.Mem_DOB = (Convert.ToDateTime(reader["Mem_DOB"]));
                        mb.Mem_BGr = (string)reader["Mem_BGr"];
                        mb.Mem_WAnn = (Convert.ToDateTime(reader["Mem_WAnn"]));
                        mb.Mem_Spouse = (string)reader["Mem_Spouse"];
                   }
                }
                catch (Exception e) { throw e; }
                finally { if (con.State == System.Data.ConnectionState.Open) con.Close(); }
            } 
        }
        return mb;
    }

这显示了错误

无法将“System.DBNull”类型的对象转换为“System.String”类型。

( Mem_Email, MPh.. etc 有时包含一个NULL值.. 如果该值为 null 我想返回 null)。任何人请帮助我。

4

6 回答 6

3

如果您应该对所有其他变量执行相同的操作,请简短说明:

 mb.Mem_Email = reader["Mem_Email"] == System.DBNull.Value ? null : (string) reader["Mem_Email"];
于 2013-08-30T08:18:43.740 回答
3

您可以使用 dapper ( http://www.nuget.org/packages/Dapper )之类的工具为自己省去很多痛苦:

public MemberBasicData GetMemberProfile(int id)
{
    using (var con = new SqlConnection(Config.ConnectionString))
    {
        return con.Query<MemberBasicData>(
            "SELECT * FROM Mem_Basic WHERE Id=@id",
            new { id } // full parameterization, done the easy way
        ).FirstOrDefault();
    }
}

这样做的事情:

  • 进行正确的参数化(为了性能和安全),但没有任何不便
  • 为您完成所有具体化、处理空值(在参数和列中)
  • 进行了疯狂的优化(基本上,它与自己编写所有代码的速度几乎相同,除了出错的事情更少)
于 2013-08-30T08:21:14.843 回答
2

除了 King King 的回答,您可以编写如下代码:

mb.Mem_Email = reader["Mem_Email"] as string;

对于值类型,如果列允许空值,最好将它们映射到 C# 中的可空值类型,以便此代码reader["Mem_DOB"] as DateTime?正常工作

于 2013-08-30T08:22:41.627 回答
0

更改所有列,这可能是 NULL

mb.Mem_NA = (string)reader["Mem_NA"];

到那个

mb.Mem_NA = reader["Mem_NA"].ToString();
于 2013-08-30T08:22:25.353 回答
0

处理可为空的字段:

mb.Mem_Email = System.DBNull.Value.Equals(reader["Mem_Email"])?"":
                                      (string)reader["Mem_Email"];

对 mb.Mem_MPh、mb.Mem_BGr 和 mb.Mem_Spouse执行相同操作。

于 2013-08-30T08:22:58.300 回答
0

我的意思不是听起来像一个 SQL 偏执狂(这当然意味着我的意思是听起来像一个 SQL 偏执狂),但如果您遵循 SQL 最佳实践并使用列列表而不是 SELECT * 您可以通过使用解决此问题可空列上的 COALESCE 因此:

SELECT
  [Id],
  [Mem_NA],
  [Mem_Occ],
  [Mem_Role],
  COALESCE( [Mem_Email], '' ) AS [Mem_Email],
  COALESCE( [Mem_MPh], '' ) AS [Mem_MPh],
  COALESCE( [Mem_DOB], CAST( '1753-1-1' AS DATE ) ) AS [Mem_DOB],
  COALESCE( [Mem_BGr, '' ) AS [Mem_BGr],
  COALESCE( [Mem_WAnn], CAST( '1753-1-1' AS DATE ) ) AS [Mem_WAnn],
  COALESCE( [Mem_Spouse], '' ) AS [Mem_Spouse]
FROM 
  [dbo].[Mem_Basic];

您的 c# 代码现在可以可靠地处理结果集,而不必考虑异常值(日期是例外;您可能应该检查您在 COALESCE 中使用的默认值(我在上面的例子),并适当地处理它们。

此外,您可以摆脱 C# 代码中的 finally 块。您将连接包装在“使用”块中;当您超出范围时,它将自动关闭连接(这是“使用”块的目的)。

于 2019-01-15T23:25:41.883 回答