LINQ to Objectについて

LINQ to Objectはとても便利だけど、DataTableとかDataSetを使ったサンプルがあんまりないので、メモ。
DataTable自体があまり使われないのかもしれないけど、データベースからとってきた値をとりあえず入れて使う分には使いやすいのでよく使う。
プログラマーによってクラスの作り方がバラバラだったり、共通関数に渡すときに統一できたりとか、Webサービスからデータを渡すときに簡単に渡せたりするんで結構重宝している。

CSVとデータベースの値を結合したり、CSVとCSVを結合したりするときにもSQLみたいに書きたい要望があったりするのでそのサンプル。
※まれにデータが数百万行あったりして、SQLよりもLINQで処理したほうが早いケースがあったりするときに書き直したりする。

VB.NET ====

    ''' <summary>
    ''' Left Join
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnLeftJoin_Click(sender As Object, e As EventArgs) Handles btnLeftJoin.Click
        Dim dtUri As New DataTable
        Dim drUriSample As DataRow

        ' ▼ 売上データ
        dtUri.Columns.Add(New DataColumn("売上No", GetType(Integer)))
        dtUri.Columns.Add(New DataColumn("売上日", GetType(String)))
        dtUri.Columns.Add(New DataColumn("得意先CD", GetType(String)))
        dtUri.Columns.Add(New DataColumn("商品名", GetType(String)))
        dtUri.Columns.Add(New DataColumn("売上数量", GetType(Decimal)))
        dtUri.Columns.Add(New DataColumn("売上金額", GetType(Decimal)))

        '   テストデータ
        drUriSample = dtUri.NewRow
        drUriSample("売上No") = 1
        drUriSample("売上日") = "20171031"
        drUriSample("得意先CD") = "00001"
        drUriSample("商品名") = "パソコン"
        drUriSample("売上数量") = 1
        drUriSample("売上金額") = 150000
        dtUri.Rows.Add(drUriSample)

        drUriSample = dtUri.NewRow
        drUriSample("売上No") = 2
        drUriSample("売上日") = "20171031"
        drUriSample("得意先CD") = "00002"
        drUriSample("商品名") = "マウス"
        drUriSample("売上数量") = 1
        drUriSample("売上金額") = 3000
        dtUri.Rows.Add(drUriSample)

        drUriSample = dtUri.NewRow
        drUriSample("売上No") = 1
        drUriSample("売上日") = "20171031"
        drUriSample("得意先CD") = "00001"
        drUriSample("商品名") = "モニター"
        drUriSample("売上数量") = 2
        drUriSample("売上金額") = 30000
        dtUri.Rows.Add(drUriSample)


        ' ▼ 得意先データ
        Dim dtTok As New DataTable
        Dim drTokSample As DataRow

        dtTok.Columns.Add(New DataColumn("得意先CD", GetType(String)))
        dtTok.Columns.Add(New DataColumn("得意先名", GetType(String)))
        dtTok.Columns.Add(New DataColumn("備考", GetType(String)))

        '   テストデータ
        drTokSample = dtTok.NewRow
        drTokSample("得意先CD") = "00001"
        drTokSample("得意先名") = "株式会社 システム作ろう"
        drTokSample("備考") = ""
        dtTok.Rows.Add(drTokSample)

        drTokSample = dtTok.NewRow
        drTokSample("得意先CD") = "00002"
        drTokSample("得意先名") = "株式会社 いろいろ販売"
        drTokSample("備考") = ""
        dtTok.Rows.Add(drTokSample)

        Dim dtUriIchiran As New DataTable
        Dim drIchiran As DataRow

        ' ▼ 売上一覧
        dtUriIchiran.Columns.Add(New DataColumn("売上No", GetType(Integer)))
        dtUriIchiran.Columns.Add(New DataColumn("売上日", GetType(String)))
        dtUriIchiran.Columns.Add(New DataColumn("得意先CD", GetType(String)))
        dtUriIchiran.Columns.Add(New DataColumn("得意先名", GetType(String)))
        dtUriIchiran.Columns.Add(New DataColumn("売上数量", GetType(Decimal)))
        dtUriIchiran.Columns.Add(New DataColumn("売上金額", GetType(Decimal)))

        Dim lnqIchiran = From drUri In dtUri.AsEnumerable
                         Group Join drTok In dtTok
                         On drUri("得意先CD") Equals drTok("得意先CD")
                         Into grp = Group
                         From drTokEmpty In grp.DefaultIfEmpty
                         Select New With {
                             .売上No = drUri("売上No"),
                             .売上日 = drUri("売上日"),
                             .得意先CD = drUri("得意先CD"),
                             .得意先名 = If(drTokEmpty("得意先名") Is Nothing, "", drTokEmpty("得意先名")),
                             .売上数量 = drUri("売上数量"),
                             .売上金額 = drUri("売上金額")
                             }

        For Each lnqdr In lnqIchiran
            drIchiran = dtUriIchiran.NewRow
            drIchiran("売上No") = lnqdr.売上No
            drIchiran("売上日") = lnqdr.売上日
            drIchiran("得意先CD") = lnqdr.得意先CD
            drIchiran("得意先名") = lnqdr.得意先名
            drIchiran("売上数量") = lnqdr.売上数量
            drIchiran("売上金額") = lnqdr.売上金額
            dtUriIchiran.Rows.Add(drIchiran)
        Next

    End Sub


C# ====


        private void btnLeftJoin_Click(object sender, EventArgs e)
        {
            DataTable dtUri = new System.Data.DataTable();
            DataRow drUriSample = null;

            // ▼ 売上データ

            dtUri.Columns.Add(new DataColumn("売上No", typeof(int)));
            dtUri.Columns.Add(new DataColumn("売上日", typeof(string)));
            dtUri.Columns.Add(new DataColumn("得意先CD", typeof(string)));
            dtUri.Columns.Add(new DataColumn("商品名", typeof(string)));
            dtUri.Columns.Add(new DataColumn("売上数量", typeof(decimal)));
            dtUri.Columns.Add(new DataColumn("売上金額", typeof(decimal)));

            //   テストデータ
            drUriSample = dtUri.NewRow();
            drUriSample["売上No"] = 1;
            drUriSample["売上日"] = "20171031";
            drUriSample["得意先CD"] = "00001";
            drUriSample["商品名"] = "パソコン";
            drUriSample["売上数量"] = 1;
            drUriSample["売上金額"] = 150000;
            dtUri.Rows.Add(drUriSample);

            drUriSample = dtUri.NewRow();
            drUriSample["売上No"] = 2;
            drUriSample["売上日"] = "20171031";
            drUriSample["得意先CD"] = "00002";
            drUriSample["商品名"] = "マウス"; ;
            drUriSample["売上数量"] = 1;
            drUriSample["売上金額"] = 3000;
            dtUri.Rows.Add(drUriSample);

            drUriSample = dtUri.NewRow();
            drUriSample["売上No"] = 1;
            drUriSample["売上日"] = "20171031";
            drUriSample["得意先CD"] = "00001";
            drUriSample["商品名"] = "モニター";
            drUriSample["売上数量"] = 2;
            drUriSample["売上金額"] = 30000;
            dtUri.Rows.Add(drUriSample);


            // ▼ 得意先データ
            DataTable dtTok = new DataTable();
            DataRow drTokSample = null;

            dtTok.Columns.Add(new DataColumn("得意先CD", typeof(string)));
            dtTok.Columns.Add(new DataColumn("得意先名", typeof(string)));
            dtTok.Columns.Add(new DataColumn("備考", typeof(string)));

            //   テストデータ
            drTokSample = dtTok.NewRow();
            drTokSample["得意先CD"] = "00001";
            drTokSample["得意先名"] = "株式会社 システム作ろう";
            drTokSample["備考"] = "";
            dtTok.Rows.Add(drTokSample);

            drTokSample = dtTok.NewRow();
            drTokSample["得意先CD"] = "00004";
            drTokSample["得意先名"] = "株式会社 いろいろ販売";
            drTokSample["備考"] = "";
            dtTok.Rows.Add(drTokSample);


            DataTable dtUriIchiran = new DataTable();
            DataRow drIchiran = null;

            // ▼ 売上一覧
            dtUriIchiran.Columns.Add(new DataColumn("売上No", typeof(int)));
            dtUriIchiran.Columns.Add(new DataColumn("売上日", typeof(string)));
            dtUriIchiran.Columns.Add(new DataColumn("得意先CD", typeof(string)));
            dtUriIchiran.Columns.Add(new DataColumn("得意先名", typeof(string)));
            dtUriIchiran.Columns.Add(new DataColumn("売上数量", typeof(decimal)));
            dtUriIchiran.Columns.Add(new DataColumn("売上金額", typeof(decimal)));

            var lnqIchiran = from drUri in dtUri.AsEnumerable()
                             join drTok in dtTok.AsEnumerable()
                             on drUri["得意先CD"] equals drTok["得意先CD"]
                             into tokGroup
                             from drTokEmpty in tokGroup.DefaultIfEmpty()
                             select new
                             {
                                 売上No = drUri["売上No"],
                                 売上日 = drUri["売上日"],
                                 得意先CD = drUri["得意先CD"],
                                 得意先名 = (drTokEmpty == null) ? "" : drTokEmpty["得意先名"],
                                 売上数量 = drUri["売上数量"],
                                 売上金額 = drUri["売上金額"]
                             };

            foreach (var lnqdr in lnqIchiran)
            {
                drIchiran = dtUriIchiran.NewRow();
                drIchiran["売上No"] = lnqdr.売上No;
                drIchiran["売上日"] = lnqdr.売上日;
                drIchiran["得意先CD"] = lnqdr.得意先CD;
                drIchiran["得意先名"] = lnqdr.得意先名;
                drIchiran["売上数量"] = lnqdr.売上数量;
                drIchiran["売上金額"] = lnqdr.売上金額;
                dtUriIchiran.Rows.Add(drIchiran);
            }

        }

===========

on句で結合するときに別の関数を間に挟んだりできるので結構便利

例)Private MaeZero(string Value,int Keta) As String   ->前ゼロ梅する関数


        Dim lnqIchiran = From drUri In dtUri.AsEnumerable
                         Group Join drTok In dtTok
                         On MaeZero(drUri("得意先CD"),5) Equals MaeZero(drTok("得意先CD"),5)
                         Into grp = Group
                         From drTokEmpty In grp.DefaultIfEmpty
                         Select New With {
                             .売上No = drUri("売上No"),
                             .売上日 = drUri("売上日"),
                             .得意先CD = drUri("得意先CD"),
                             .得意先名 = If(drTokEmpty("得意先名") Is Nothing, "", drTokEmpty("得意先名")),
                             .売上数量 = drUri("売上数量"),
                             .売上金額 = drUri("売上金額")
                             }

ただ、プロジェクト単位である程度書き方を統一しておかないとプログラマさんによっては書き方が全然違うので保守とか考えるときは注意したほうがいい。

みんなが知識ある人ばっかりだったらそんなに気にしなくてもいいかもしれないけど、開発の後半になって仕様変更とかで危なそうな個所を探すときにも書き方が一緒じゃないとGrepしても引っかからなかったりする。

パッと見でもわからないし・・・。

0 件のコメント:

コメントを投稿

PowerShellでEdgeを自動化(インストール不要。参考:郵便追跡サービス自動操作)

1.経緯について  RPAのソフトをインストールできないので、これまでVBSでCreateObjectでブラウザの自動操作をすることがたまにあった。 ※いざというときの手札として持っているだけで安心感が段違い  見た目上IEがインストールされていなくても、CreateObject...