5

質問:

SQL結果をデータテーブルではなくクラスのリストとして取得するメソッドを作成しました。問題は、データベースにintフィールドがあり、null許容であるということです。

行を。でヒットすると、nullの代わりにNULL int戻りDataReaderます。に変換できないため、例外をスローDbNull.Valueします。System.Convert.ChangeType(objVal, fi.FieldType)DbNullint

これまでのところ悪い。objVal私が比較したとき、私は問題を解決したと思いました、DbNull.Valueそして本当なら、代わりにこれをしました: System.Convert.ChangeType(null, fi.FieldType)

残念ながら、結果の整数型はNULLではなく0であることに気づきました。

だから私はクラスのint型をに変更しようとしましたNullable<int>が、値がそうでない場合、に変換できないために例外がスローされるという問題DbNull.ValueChangeTypeありintますnullable<int>...

そこで、ここで、によって返されるオブジェクトのタイプを検出し、datareaderそれをnull許容値に変換しようとします。

tTypeForNullable として正しく表示されNullable<int>ます。しかし、結果タイプを見ると、次のようになりますint

何故ですか ?そしてもっと重要なこと:どうすればそれを適切に行うことができますか?

typeはオブジェクトであるため、ジェネリックメソッドを使用してを作成することはできないことに注意してくださいNullable<int>

bool bisnull = IsNullable(objVal);
bool bisnullt = IsNullable(fi.FieldType);

if (bisnullt)
{
    Type tTypeForNullable = typeof(Nullable<>).MakeGenericType(objVal.GetType());

    //object result = Activator.CreateInstance(tTypeForNullable, new object[] { objVal });
    //object result = Activator.CreateInstance(typeof(Nullable<int>), new object[] { objVal });
    object result = Activator.CreateInstance(tTypeForNullable, objVal);
    Type tres = result.GetType();
    fi.SetValue(tThisValue, System.Convert.ChangeType(result, fi.FieldType));
}

参照用の完全なルーチンは次のとおりです。

public virtual System.Collections.Generic.IList<T> GetList<T>(System.Data.IDbCommand cmd)
        {
            System.Collections.Generic.List<T> lsReturnValue = new System.Collections.Generic.List<T>();
            T tThisValue = default(T);
            Type t = typeof(T);

            lock (cmd)
            {
                using (System.Data.IDataReader idr = ExecuteReader(cmd))
                {

                    lock (idr)
                    {

                        while (idr.Read())
                        {
                            //idr.GetOrdinal("")
                            tThisValue = Activator.CreateInstance<T>();

                            // Console.WriteLine(idr.FieldCount);
                            for (int i = 0; i < idr.FieldCount; ++i)
                            {
                                string strName = idr.GetName(i);
                                object objVal = idr.GetValue(i);


                                System.Reflection.FieldInfo fi = t.GetField(strName);
                                //Type tttttt = fi.FieldType;
                                if (fi != null)
                                {
                                    //fi.SetValue(tThisValue, System.Convert.ChangeType(objVal, fi.FieldType));
                                    if (objVal == System.DBNull.Value)
                                    {
                                        objVal = null;
                                        fi.SetValue(tThisValue, null);
                                    }
                                    else
                                    {
                                        //System.ComponentModel.TypeConverter conv = System.ComponentModel.TypeDescriptor.GetConverter(fi.FieldType);

                                        bool bisnull = IsNullable(objVal);
                                        bool bisnullt = IsNullable(fi.FieldType);

                                        if (bisnullt)
                                        {
                                            Type tTypeForNullable = typeof(Nullable<>).MakeGenericType(objVal.GetType());

                                            //object result = Activator.CreateInstance(tTypeForNullable, new object[] { objVal });
                                            //object result = Activator.CreateInstance(typeof(Nullable<int>), new object[] { objVal });
                                            object result = Activator.CreateInstance(tTypeForNullable, objVal);
                                            Type tres = result.GetType();
                                            fi.SetValue(tThisValue, System.Convert.ChangeType(result, fi.FieldType));
                                        }
                                        fi.SetValue(tThisValue, System.Convert.ChangeType(objVal, fi.FieldType));
                                    }
                                }
                                else
                                {
                                    System.Reflection.PropertyInfo pi = t.GetProperty(strName);
                                    if (pi != null)
                                    {
                                        //pi.SetValue(tThisValue, System.Convert.ChangeType(objVal, pi.PropertyType), null);


                                        if (objVal == System.DBNull.Value)
                                        {
                                            objVal = null;
                                            pi.SetValue(tThisValue, null, null);
                                        }
                                        else
                                        {
                                            pi.SetValue(tThisValue, System.Convert.ChangeType(objVal, pi.PropertyType), null);
                                        }


                                    }
                                    // Else silently ignore value
                                } // End else of if (fi != null)

                                //Console.WriteLine(strName);
                            } // Next i

                            lsReturnValue.Add(tThisValue);
                        } // Whend

                        idr.Close();
                    } // End Lock idr

                } // End Using idr

            } // End lock cmd

            return lsReturnValue;
        } // End Function GetList

これとともに:

public System.Data.IDataReader ExecuteReader(System.Data.IDbCommand cmd)
        {
            System.Data.IDataReader idr = null;

            lock(cmd)
            {
                System.Data.IDbConnection idbc = GetConnection();
                cmd.Connection = idbc;

                if (cmd.Connection.State != System.Data.ConnectionState.Open)
                    cmd.Connection.Open();

                idr = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
            } // End Lock cmd

            return idr;
        } // End Function ExecuteReader

typeはオブジェクトであるため、ジェネリックメソッドを使用してを作成することはできないことに注意してくださいNullable<int>

4

1 に答える 1

3

あなたはボックス化しています - そして、null 許容値型のボックス化操作の結果は、その型のボックス化された値になることはありません。null または null 非許容値型です。詳細については、 MSDNを参照してください。

于 2012-06-14T10:38:45.700 に答える