从SQL Server表中选择NULL值
本文关键字:选择 NULL SQL Server | 更新日期: 2023-09-27 18:29:33
我正在使用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
...等有时包含NULL
值。如果该值为null,我希望返回null)。任何人都请帮帮我。
只要做一些简短的if,就应该对所有其他变量做同样的操作:
mb.Mem_Email = reader["Mem_Email"] == System.DBNull.Value ? null : (string) reader["Mem_Email"];
使用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();
}
}
它的作用:
- 进行了正确的参数化(为了性能和安全),但没有任何不便
- 为您执行所有的具体化,处理null(参数和列中)
- 是疯狂优化的(基本上,它的速度与自己编写所有代码的速度相当,只是出错的地方更少)
除了King King的答案,您还可以编写这样的代码:
mb.Mem_Email = reader["Mem_Email"] as string;
对于值类型,如果列允许null,那么在C#中将它们映射到可为null的值类型是一种很好的做法,这样代码reader["Mem_DOB"] as DateTime?
就可以在中工作
更改所有列,该中可能为NULL
mb.Mem_NA = (string)reader["Mem_NA"];
到
mb.Mem_NA = reader["Mem_NA"].ToString();
处理可为null的字段:
mb.Mem_Email = System.DBNull.Value.Equals(reader["Mem_Email"])?"":
(string)reader["Mem_Email"];
执行相同的操作:兆字节Mem_MPh,mb。Mem_BGr和mb。Mem_Spouse。
我的意思不是听起来像SQL偏执狂(当然,这意味着我DO的意思是听起来像SQL偏见),但如果你遵循SQL最佳实践,使用列列表而不是SELECT*,你可以通过在可为null的列上使用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中使用的默认值(我在上面的示例中使用了SQL Date变量的最小允许值),并适当地处理它们。
此外,您还可以在c#代码中去掉finally块。您将连接封装在"using"块中;当您超出范围时,它将自动关闭连接(这就是"使用"块的目的)。