1

次のようなカスタム クラスがあるとします。

public class Customer    
{        
 public int CustomerID { get; set; }        
 public string CompanyName { get; set; }        
 public string BusinessAddress { get; set; }        
 public string Phone { get; set; } 
 public int ParentID { get; set; } 
}

データリーダーを使用して、データベースからカスタム オブジェクトを作成します。元:

  while (dr.Read())
  {
    listCustomers.Add(new Customer(
          Convert.ToInt32(dr["CustomerID"]),
          Convert.ToString(dr["CompanyName"]),
          Convert.ToString(dr["BusinessAddress"]),
          Convert.ToString(dr["Phone"]),
          Convert.ToInt32(dr["ParentID"]),
)

ParentID は、データベースで null にすることができます (変更することはできません)。null の場合、変換は明らかに失敗します。

DB から取得した null 値をどのように処理してビジネス オブジェクトに入力すればよいですか? カスタム クラスで Nullable 型を使用するのは良い方法でしょうか? 他のヒントはありますか?

4

6 に答える 6

6

絶対。Null 許容型はまったく問題ありません。それ以外の場合は、「ParentID が -1 の場合、これはCustomer親がないことを意味します」という愚かな規則を考え出す必要があります。Null 許容型は、これを「設計により」強制します。親がない場合は、ParentIDになりますnull

オブジェクトのハイドレートに関しては、ORM ツール ( NHibernateBLToolkitなど) の使用を検討してください。これは、SQL クエリの作成とデータ リーダーからのオブジェクトの入力に開発時間の 50% を費やしたくないためです。

于 2009-10-06T10:29:48.357 に答える
3

ビジネス オブジェクトで null 許容型を使用します。次に、このような一般的なヘルパー メソッドを使用して、データベースから null 許容フィールドを取得できます。

public static T? GetValue<T>(IDataRecord record, string columnName)
    where T : struct
{
    int columnIndex = record.GetOrdinal(columnName);
    if (record.IsDBNull(columnIndex))
        return null;
    else
        return (T)Convert.ChangeType(record[columnIndex], typeof(T));
}

したがって、行をロードするときに次のようにParentId宣言されている場合。int?

obj.ParentId = GetValue<int>(dr, "ParentId");
于 2009-10-06T10:52:12.047 に答える
2

このようなヘルパーを追加するのはどうですか?

    static string safeGetStringFromDB( IDataReader dr, string strField )
    {
        int nIndex = dr.GetOrdinal( strField );
        if ( dr.IsDBNull( nIndex ) )
            return string.Empty;
        return dr.GetString( nIndex );
    }
于 2009-10-06T10:31:38.680 に答える
2

Nullable types are fine for nullable fields.

Handle the assignment with a ternary :-

ParentID = ( dr["ParentID"] is DBNull ) ? null : (int)dr["ParentID"];

Also, you don't need to use Convert if you know what your underlying db fields are and their .NET representations.

I restrict use of convert to situations where I know the types are different ( say int to string ).

When I know the .NET corresponding type, I'll simply cast :-

listCustomers.Add(new Customer(
          (int)dr["CustomerID"],
          (string)dr["CompanyName"],
          (string)dr["BusinessAddress"],
          (string)dr["Phone"],
          ( dr["ParentID"] is DBNull ) ? null : (int)dr["ParentID"]));

Finally, when using nullable types, be aware that overloading a method can be a potential problem.

Consider the following examples :-

public void Populate( int? facilityId, string name, bool? somethingElse )...
public void Populate( string facilityCode, string name, bool? somethingElse )...

Same number of arguments, all params potentially null. When the first parameter is null, you might be surprised on the interpretation your compiler eventually picks. Has caught me out before, anyway.

于 2009-10-06T10:45:35.593 に答える
1

このようなヘルパーメソッドを作成できます。

        static T Map<T>(object obj, Func<object, T> map, T def)
    {
        if (obj != null)
        {
            return map(obj);
        }
        return def;
    }

    static T Map<T>(object obj, Func<object, T> map)
    {
        return Map<T>(obj, map, default(T));
    }

そしてそれらを次のように使用します:

            object o = 1;
        var t = Map(o, Convert.ToInt32, 0); // with default value
        var t2 = Map(o, Convert.ToInt32); // or without default value
于 2009-10-06T10:32:12.593 に答える
0

ParentIDはクラス内の文字列であり、Int32に変換しています。

しかし、それはさておき、あなたはデータベースを知っているので、どのフィールドがnullになる可能性があるかを知っています。私の意見では、これがデータベースを可能な限りモデル化するための最良の方法であるため、データオブジェクトでもこれらのフィールドをすべてnull許容にします。

于 2009-10-06T10:32:28.350 に答える