none
CSV取込からデータベース登録時の型変換について RRS feed

  • 質問

  • visual stido2019Commity でmicrosoft Sql server2016にentity framework coreを使用してCSVファイルの内容をデータベースに登録しようとしています。

    CSVファイルの内容は一列が以下のような「" "」で囲まれたテキストと日付、囲まれていない数値などの内容になっています。

    "00","T010006413","2013/08/13","010006","K.K",0.25

    これをデータベースに登録しようとして以下の順に処理を行っています。

    ①StreamReaderを使用して1行づつ読込(string型)

    ②不要な「" "」を変換して「、」でsplitして配列に格納

    ③配列をリストに格納

    ④データベースに登録

    この方法だと全ての要素の型がstringなため、データベースの型タイプが文字型であれば問題ないのですが、型タイプが数値型、日付型、money型などがあるため、型に合わせようとするとエラー(ビルド出来ない)になります。

    そこで教えて頂きたいのですが、以下の事を実現するにはどうすればよいのでしょうか?

    ・データベースのテーブルのクラスを利用してリストを使用するには(string型に読み込まないでの処理)どうすればよいのでしょうか?

     var lists = new List<table_class>();   <-この中にCSVファイルの中身を格納を出来ればしたいです。

    ・string型で処理をしなければならない場合は最後のキャストしたいのですが、配列の特定の要素だけをキャストするにはどうすればよいのでしょうか?

     コード = lists[0], <- 特定の要素だけキャストしたい

    よろしくお願い致します。

    データベース登録処理部

    using (var reader = new StreamReader(item, Encoding.GetEncoding("shift_jis")))
                            {
                                while (!reader.EndOfStream)
                                {
                                    var line = reader.ReadLine();

                                    var changeLine = line.Replace("\"", "");

                                    //読み込んだ一行をカンマ毎に分けて配列に格納する
                                    string[] values = changeLine.Split(',');
                                    // 配列からリストに格納する
                                    List<string> lists = new List<string>();
                                    lists.AddRange(values);

                                    //データベース登録
                                    using (var db = new DBmasterContext())
                                    {
                                        var Netbmsデータ1 = new Netbmsデータ
                                        {
                                            コード = lists[0],
                                            予定日 = lists[11],                                        
                                            単価 = lists[21],
                                            
                                        };
                                        db.Netbmsデータs.Add(Netbmsデータ1);
                                        db.SaveChanges();
                                    }
                                    
                                }
                            }

    テーブルのクラス

    public partial class Netbmsデータ
        {
            public int Id { get; set; }
            public string コード { get; set; }
            public string 予定日 { get; set; }     //date型にする予定   
            public decimal? 単価 { get; set; }    // 型がstringでないためエラー
        }

    2021年5月23日 3:03

回答

  • 該当の SQL Server は、その CSV ファイルにアクセスできるのでしょうか。
    それとも C# 側のみが CSV にアクセスできるのでしょうか。

    型タイプが数値型、日付型、money型などがあるため、型に合わせようとするとエラー(ビルド出来ない)になります。

    CSV ファイルに対して、ODBC Text Driver を使ってアクセスするのは如何でしょうか。schema.ini で、それぞれの列の型を指定できます。

    https://docs.microsoft.com/ja-jp/sql/odbc/microsoft/schema-ini-file-text-file-driver?view=sql-server-ver15

    また、コントロール パネルの ODBC データソース アドミニストレータ― から ODBC ドライバーのセットアップを行えば、[書式の定義(F)...]ボタンで表示される【テキスト形式の定義】ダイアログから、schema.ini を手動で生成することもできます。

    • 回答としてマーク Piggy0078 2021年5月25日 6:13
    2021年5月23日 4:18
  • 以下の記事に、CSV ファイルの各列の型を Schema.ini ファイルを使用して指定し、 ADO.NET + OelDb + JET を利用して DataTable を生成した際、DataTable の各 DataColumn に型が反映されるようにした例が載っています。

    CSV ファイルを DataGridView に表示
    http://surferonwww.info/BlogEngine/post/2020/09/11/show-date-in-csv-file-on-datagridview.aspx

    その DataTable から DB に登録すればやりたいことはできると思います。
    • 回答としてマーク Piggy0078 2021年5月25日 6:13
    2021年5月23日 4:26
  • Hoshina です
    こんにちは

    色々のやり方があるでしょうが、私が作製したプログラムで実績があるのは、以下のものです。

    ・名前空間、Microsoft.VisualBasic.FileIO; にある TextFieldParser クラスを使用する

    特徴は、
    ・エンコードを指定して、 CSV ファイルの解析ができる
    ・ダブルクォーテーションで囲まれている/いない 項目が混在していても解析できる
    ・ダブルクォーテーションの中にある「,」は文字列として正しく解析できる
     単純に「,」を取り除くだけでは、この部分が難しいかも
    ・ダブルクォーテーションの中にある2つ連続したダブルクォーテーションは、1つのダブルクォーテーションとして解析できる
     単純にダブルクォーテーションを取り除くだけでは、この部分が難しいかも
    ・解析した結果は、文字列になるので、適宜変換する

    VisualBasic の名前空間ですが、C# からも使用できます。参考まで。

    それでは
    • 回答としてマーク Piggy0078 2021年5月25日 6:13
    2021年5月23日 8:43

すべての返信

  • 該当の SQL Server は、その CSV ファイルにアクセスできるのでしょうか。
    それとも C# 側のみが CSV にアクセスできるのでしょうか。

    型タイプが数値型、日付型、money型などがあるため、型に合わせようとするとエラー(ビルド出来ない)になります。

    CSV ファイルに対して、ODBC Text Driver を使ってアクセスするのは如何でしょうか。schema.ini で、それぞれの列の型を指定できます。

    https://docs.microsoft.com/ja-jp/sql/odbc/microsoft/schema-ini-file-text-file-driver?view=sql-server-ver15

    また、コントロール パネルの ODBC データソース アドミニストレータ― から ODBC ドライバーのセットアップを行えば、[書式の定義(F)...]ボタンで表示される【テキスト形式の定義】ダイアログから、schema.ini を手動で生成することもできます。

    • 回答としてマーク Piggy0078 2021年5月25日 6:13
    2021年5月23日 4:18
  • 以下の記事に、CSV ファイルの各列の型を Schema.ini ファイルを使用して指定し、 ADO.NET + OelDb + JET を利用して DataTable を生成した際、DataTable の各 DataColumn に型が反映されるようにした例が載っています。

    CSV ファイルを DataGridView に表示
    http://surferonwww.info/BlogEngine/post/2020/09/11/show-date-in-csv-file-on-datagridview.aspx

    その DataTable から DB に登録すればやりたいことはできると思います。
    • 回答としてマーク Piggy0078 2021年5月25日 6:13
    2021年5月23日 4:26
  • Hoshina です
    こんにちは

    色々のやり方があるでしょうが、私が作製したプログラムで実績があるのは、以下のものです。

    ・名前空間、Microsoft.VisualBasic.FileIO; にある TextFieldParser クラスを使用する

    特徴は、
    ・エンコードを指定して、 CSV ファイルの解析ができる
    ・ダブルクォーテーションで囲まれている/いない 項目が混在していても解析できる
    ・ダブルクォーテーションの中にある「,」は文字列として正しく解析できる
     単純に「,」を取り除くだけでは、この部分が難しいかも
    ・ダブルクォーテーションの中にある2つ連続したダブルクォーテーションは、1つのダブルクォーテーションとして解析できる
     単純にダブルクォーテーションを取り除くだけでは、この部分が難しいかも
    ・解析した結果は、文字列になるので、適宜変換する

    VisualBasic の名前空間ですが、C# からも使用できます。参考まで。

    それでは
    • 回答としてマーク Piggy0078 2021年5月25日 6:13
    2021年5月23日 8:43
  • 皆様、回答ありがとうございます。

    両方とも方法を知りませんでした。

    それぞれ作成して使用感を確認してみます。

    2021年5月25日 6:14
  • 今更ながらですが、DataTable を作れば DataAdapter を利用して SQL Server のデータの更新ができるという記事をご参考に紹介しておきます。

    DataAdapter を使用してデータ ソースを更新する
    https://docs.microsoft.com/ja-jp/sql/connect/ado-net/update-data-sources-with-dataadapters?view=sql-server-ver15

    上の記事のようなやり方ではなくて、質問に書いてあったように Entity Framework を使いたいという場合は TextFieldParser を使って CSV ファイルを読むことをお勧めします。

    TextFieldParser を使ってCSV ファイルから一行ずつ読んで、読んだ結果の string[] を「Netbmsデータ」クラスの各プロパティに必要に応じてキャストしてからに代入し、db.Netbmsデータs.Add(Netbmsデータ1); ⇒ db.SaveChanges(); するということでいかがですか?


    2021年5月25日 8:23