2008-11-25 78 views
2

我有一个拥有用户可选配置文件的数据库。在配置文件中我有字符串,字符(用于M或F)和整数。从SQL数据库中处理null int/char的最佳做法是什么?

我遇到了一个问题,我尝试将用户的性别放入Profile对象的属性中,并且应用程序崩溃,因为它不知道如何处理返回的空值。

我尝试了数据流延到合适的类型

char sex = (char)dt.Rows[0]["Sex"]; 

这并没有解决我的问题。然后我尝试将类型更改为Nullable和Nullable,并获得所有相同的转换问题。我目前能找到的解决方案如下:

object.sex = null; 
if(dt.Rows[0]["Sex"] != DBNull.Value) 
     object.sex = (char)dt.Rows[0]["Sex"]; 
object.WorkExt = null; 
if(dt.Rows[0]["WorkExt"] != DBNull.Value) 
     object.WorkExt = (int)dt.Rows[0]["WorkExt"]; 

有没有更简单或更好的方法来做到这一点?还是我在正确的轨道上?

回答

3

rotard的回答(用Is<ColumnName>Null())仅适用于类型化的数据集。

对于无类型的数据集,您必须使用以下代码中的一种模式。如果此代码不是确定性的,请告诉我,我将对其进行编辑,直到它为止。这是一个非常普遍的问题,应该只有一个正确的答案。

using System. 
using System.Data; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     DataTable dt = new DataTable(); 
     dt.Columns.Add("test", typeof (char)); 
     dt.Columns["test"].AllowDBNull = true; 

     DataRow dr = dt.Rows.Add(); 
     char? test; 

     try 
     { 
      test = (char?)dr["test"]; 
     } 
     catch (InvalidCastException) 
     { 
      Console.WriteLine("Simply casting to a nullable type doesn't work."); 
     } 

     test = dr.Field<char?>("test"); 
     if (test == null) 
     { 
      Console.WriteLine("The Field extension method in .NET 3.5 converts System.DBNull to null.");     
     } 

     test = (dr["test"] is DBNull) ? null : (char?) dr["test"]; 
     if (test == null) 
     { 
      Console.WriteLine("Before .NET 3.5, you have to check the type of the column's value."); 
     } 

     test = (dr["test"] == DBNull.Value) ? null : (char?) dr["test"]; 
     if (test == null) 
     { 
      Console.WriteLine("Comparing the field's value to DBNull.Value is very marginally faster, but takes a bit more code."); 
     } 

     // now let's put the data back 

     try 
     { 
      dr["test"] = test; 
     } 
     catch (ArgumentException) 
     { 
      Console.WriteLine("You can't set nullable columns to null."); 
     } 

     dr.SetField("test", test); 
     if (dr["test"] is DBNull) 
     { 
      Console.WriteLine("Again, in .NET 3.5 extension methods make this relatively easy."); 
     } 

     dr["test"] = (object)test ?? DBNull.Value; 
     if (dr["test"] is DBNull) 
     { 
      Console.WriteLine("Before .NET 3.5, you can use the null coalescing operator, but note the awful cast required."); 
     } 


     Console.ReadLine(); 
    } 
} 
0

我会和你一样做。我会写一个函数为它:

的东西做:

object.sex = handle(dt.Rows[0]["Sex"]); 

在手柄你做的== DBNull.Value检查。

+0

这只是工作,如果你的函数返回一个对象,你投返回值为char?在任务中。 .NET 3.5的DataRow扩展中的Field方法为您做到这一点。 – 2008-11-25 22:26:15

1

dt是一个ADO.Net 2数据表吗?你不能这样做:

if(dt.Rows[0].IsSexNull()) {} else {} 

?另外,假设你可以控制你的数据库,那么使用一点而不是一个字符串会更有意义吗?

+0

有些人不知道如何回答这个问题,有些人不喜欢告诉你。你可以将这些组合在一起,但至少需要第三个选项。 – 2008-11-25 20:15:57

+0

真,假或空ftw – Jimmy 2008-11-25 22:40:08

3

可空类型是专为此目的而设计的!用'as char?'而不是 '(字符?)'

class Foo { 
    char? sex; 
} 
Foo object; 

object.sex = dt.Rows[0]["Sex"] as char?; 
1

怎么样:

internal static T CastTo<T>(object value) 
    { 
     return value != DBNull.Value ? (T)value : default(T); 
    } 

,然后用它喜欢:

 return new EquipmentDetails(
      CastTo<int>(reader["ID"]), 
      CastTo<int>(reader["CategoryID"]), 
      CastTo<string>(reader["Description"])); 

等等

相关问题