0

質問:以下のクラスを使用して、csvファイルを次のようにシリアル化します

List<MyCsvFileType>

次に、を List<MyCsvFileType>使用してをデータテーブルに変換します

MyConvertTo

(以下にもリストされています)。問題は、MyConvertToが列の位置を変更することです。つまり、すべてのプロパティがすべてのパブリック変数の後に来るということです。

これが引き起こす問題は、後でSqlBulkCopyを使用してDataTableをデータベーステーブルにコピーすることです。残念ながら、SqlBulkCopyは、データテーブルをデータベーステーブルに自動マッピングするために、列名ではなく列のインデックスを使用します。

つまり、float領域フィールドに英数字のAP_FL_CADKeyを挿入しようとするため、エラーメッセージが表示されます(データベーステーブルのレイアウトがクラスと同じであるため)...

MyConvertToのフィールドとプロパティの位置を取得する方法はありますか?したがって、データベーステーブル(ロット)を変更したり、BulkCopyの独自の実装を記述したりする必要はありません。これは、datatableとdatabase-tableの間のマッピングも手動で設定したくないためです。

最悪の場合、フィールドオフセットでソートすることで可能になるはずです。

クラス:

[FileHelpers.IgnoreFirst]
[FileHelpers.IgnoreEmptyLines]
public class MyCsvFileType
{
    public string FL_CADKey;
    public string FL_DWG;
    public string FL_ObjID;

    public string FL_Area;

    public double FL_Area_double
    {
        get
        {
            if (string.IsNullOrEmpty(this.FL_Area))
                return 0.0;
            else
                return System.Convert.ToDouble(this.FL_Area);
        }

    } // End Property PP_Area_double


    public string AP_FL_CADKey;


    public System.Guid UID
    {

        get
        {
            return System.Guid.NewGuid();
        }

    } // End Property UID
}

MyConvertTo:

public static DataTable MyConvertTo(dynamic custs)
{
    DataTable dt = MyCreateTable(custs);

    System.Data.DataRow dr = null;
    foreach (dynamic cli in custs)
    {
        Console.WriteLine();

        Type t = cli.GetType();

        dr = dt.NewRow();

        foreach (System.Reflection.FieldInfo fi in t.GetFields())
        {
            dr[fi.Name] = fi.GetValue(cli);
        }

        foreach (System.Reflection.PropertyInfo pi in t.GetProperties())
        {
            dr[pi.Name] = pi.GetValue(cli, null);
        }

        dt.Rows.Add(dr);
    } // Next cli

    return dt;
}



public static DataTable MyCreateTable(dynamic custs)
    {
        DataTable table = new DataTable("Table_1");

        foreach (dynamic cli in custs)
        {
            Console.WriteLine();

            Type t = cli.GetType();

            foreach (System.Reflection.FieldInfo fi in t.GetFields())
            {
                table.Columns.Add(fi.Name, fi.FieldType);
                //Console.WriteLine(fi.Name + ": " + fi.GetValue(cli));
            }

            foreach (System.Reflection.PropertyInfo pi in t.GetProperties())
            {
                table.Columns.Add(pi.Name, pi.PropertyType);
                //Console.WriteLine(pi.Name + ": " + pi.GetValue(cli, null));
            }

            break;
        } // Next cli

        return table;
    }
4

2 に答える 2

0

返されるフィールドの順序が同じであるとは限りませんが、通常は順序が定義されています。

Linq を使用して、返された配列を一貫した方法で並べ替えてから、変換を使用することをお勧めします。

于 2012-04-04T09:27:30.103 に答える
0

ColumnMappingsインスタンスに を設定して、SqlBulkCopy列名に基づいて ID マッピングを追加することはできませんか?

データ ソースと宛先テーブルの列数が同じで、データ ソース内の各ソース列の序数位置が対応する宛先列の序数位置と一致する場合、ColumnMappingsコレクションは不要です。ただし、列数が異なる場合、または序数の位置が一貫していない場合は、ColumnMappingsを使用して、データが正しい列にコピーされるようにする必要があります。

たとえば、各列を追加するときは、 を呼び出すだけ.Add(ColumnName,ColumnName)です。

于 2012-04-04T09:33:35.133 に答える