Visual Basic 中学校 掲示板 投稿内容
タグのない投稿を抽出 統計 RSS

Visual Basic 中学校 > 投稿一覧 >

LINQとSQLについて 解決済み

タグの編集...

投稿者 SSD   (社会人)   投稿日時 2022/6/21 18:42:36
XMLを操作するのにXmlDocumentクラスを用いていましたが、
比較的新しいクラスとしてXDocumentというクラスがあることを知りました。

こちらはLINQを用いてより手軽にXMLを操作できるということで、
今はこのクラスを使うことが主流というコメントを見かけました。

新しいものを使いたいと思う一方で、LINQにどうしてもなじめません。
LINQを知るよりも先にSQL ServerでSQL文を書いていたのですが、
LINQとSQLは似てるようで似ていないと言いますか、
SelectとかFromとかの順序が違うためとても気持ち悪いです...。

SQLの方が英語の文法的な順序で分かりやすく感じます。
LINQを先に知っていたら逆に思っていたかもしれませんが。

SQLとLINQの両方を使っている方はどういう考え方でこの違いを飲み込んでいますか?

投稿者 (削除されました)   ()   投稿日時 2022/6/21 20:04:09
(削除されました)

投稿者 魔界の仮面弁士   (社会人)   投稿日時 2022/6/21 20:09:41
> XMLを操作するのにXmlDocumentクラスを用いていましたが、
> 比較的新しいクラスとしてXDocumentというクラスがあることを知りました。
比較的新しいと言っても、お披露目が 2007 年秋冬ごろだったので、もう 15 年弱ほど前になるかな…?

あの当時は XML が良く使われていた時期で、Visual Basic の言語拡張として
XML データをリテラルとしてコード中に直接埋め込めるように拡張されたというのに、
その後の技術変遷で XML が下火になってしまい、今では XML リテラルの出番が
殆ど無いというさみしい状態に…。

まぁ今でも XML データは使われているので、無駄にはならないのですけれども。


> SelectとかFromとかの順序が違うためとても気持ち悪いです...。
初期段階では、同じ語順にする案もあったと聞いたことがあります。
ただ、それだとプログラムのデータ処理として扱いにくいため、現在の順序になったのだとか。


SQL では、「出力したいデータ」を先に SELECT で書いてから、
その後に FROM で「どこからそれらを取得するのか」という構文で書きますよね。
御存知のように、SELECT/FROM/WHERE/GROUP BY/ORDER BY の順で記述されるものであり、
この順番を変更することは基本的にできません。

ところが実際には SQL の世界でも、最初に評価されるのは FROM 句だったりします。
データベースにもよるでしょうけれども、たとえば
 「SELECT 存在しない列名 FROM 存在しない表名」
というクエリがあった場合、先にエラーとなるのは FROM 句側であるケースが多いです。
https://qiita.com/k_0120/items/a27ea1fc3b9bddc77fa1

そのため LINQ では、From を先頭に持ってきて、まず最初に
「データ一覧を保持しているコレクション」を得る形になりました。
この方が、インテリセンスによる入力支援も評価しやすいです。

LINQ では、コレクションが最初に置かれるという方針がありますが、その後に続く
Select / Where / Order By などの処理については、順序を入れ替えても構いません。


Where で絞り込んだ後に、残ったデータに対して Select で加工しても良いですし、
Select で加工してから、加工した結果について Where で抽出判定しても良いです。
Order By で並び替えてから、再度 Select しなおしても構いません。

これは、LINQ の肝となる【パイプライン処理】の考え方によるものです。
https://ufcpp.net/study/csharp/da_about.html



> SQLとLINQの両方を使っている方はどういう考え方でこの違いを飲み込んでいますか?
クエリ構文を使う場合は、SQL との差異が目につきますが、
メソッド構文を使っている限りは、全く気にならないですね。
(とはいえ個人的には、VB のメソッド構文があまり好きではありません)


LINQ のクエリ構文はメソッド構文の糖衣構文です。
クエリ構文で書かれたコードは、すべてメソッド構文で表せますが、その逆に
メソッド構文で書かれた LINQ は、必ずしもクエリ構文で書けるとは限りません。

そのため C# で LINQ を書く場合は、メソッド構文を好む人が多いように感じます。私もそうです。

一方 VB の場合は、ラムダ式の記述が C# よりも冗長的なこともあって、
クエリ構文の方もしばしば使われているように感じます。

特に「LINQ to XML」においては、VB だとクエリ構文の方が多く使われているイメージがあります。
私個人の感覚であって、利用度合いの数的根拠があるわけでは無いのですけれども。
(LINQ to XML を使う場合においては、個人的には C# よりも VB の構文の方が好みです)

投稿者 るきお   (社会人)   投稿日時 2022/6/21 20:15:11
魔界の仮面弁士さんも触れていますが、LINQを使う場合、次の4つのやり方があります。(他にもありますが、一応ここでは4つに絞ります。)

①VBでクエリ構文
②VBでメソッド構文
③C#でクエリ構文
④C#でメソッド構文

2022年現在、私の感覚では、④が圧倒的に多く、④ >>>> ① > ② > ③ という順番のように感じます。(個人的な感覚です。)
つまり、多くの人はクエリ構文を使っていないと感じます。

ただ、VBに限定すると、クエリ構文の方が私は好きです。VBはラムダ式をつなげていくとなんか見にくい気がするのですよね。
逆にC#ではクエリ構文がなんか見にくいです気がします。

私自身はC#ではクエリ構文はほぼ使わず。VBではクエリ構文を好みますが、SQLとの関係はまったく意識せず、別物だと思って使っています。

Dim xml = <persons>
              <person>
                  <name>徳川家康</name>
                  <address>東京都千代田区1丁目江戸城本丸</address>
              </person>
              <person>
                  <name>織田信長</name>
                  <address>滋賀県安土1丁目</address>
              </person>
          </persons>

'クエリ構文 
Dim names1 = From person In xml...<name> Select person.Value

'徳川家康,織田信長 
Debug.WriteLine(String.Join(",", names1))

'メソッド構文 
Dim names2 = (xml...<name>).Select(Function(person) person.Value)

'徳川家康,織田信長 
Debug.WriteLine(String.Join(",", names2))


VBのLINQについていろいろ書いたものがありますので、よろしければ参考にしてください。
https://www.umayadia.com/VBStandard2/Standard39.htm

投稿者 魔界の仮面弁士   (社会人)   投稿日時 2022/6/21 21:33:20
るきおさんが LINQ to XML の処理サンプルを書いてくださったので、元の xml を
下記の形式に整形する処理が、XML リテラルの有無でどのように異なるかを書いてみました。

<Root>
  <person name="徳川家康">東京都千代田区1丁目江戸城本丸</person>
  <person name="織田信長">滋賀県安土1丁目</person>
</Root>



'クエリ構文 + XML リテラルを使用 
Dim q1 = <Root><%= From p In xml...<person> Select <person name=<%= p.<name>.Value %>><%= p.<address>.Value %></person> %></Root>
MsgBox(q1.ToString())

'メソッド構文 + XML リテラル無し 
Dim q2 = New XElement("Root", xml.Descendants("person").Select(Function(p) New XElement("person"New XAttribute("name", p.Element("name").Value), p.Element("address").Value)))
MsgBox(q2.ToString())



実際には改行した方が階層が分かりやすいかな…?
C# には XML リテラルが無いので、こういう加工は VB の方が書きやすいんですよね。

'クエリ構文 + XML リテラルを使用 
Dim q1 = <Root>
             <%= From p In xml...<person>
                 Select <person name=<%= p.<name>.Value %>>
                            <%= p.<address>.Value %>
                        </person>
             %>
         </Root>
MsgBox(q1.ToString())

'メソッド構文 + XML リテラル無し 
Dim q2 = New XElement("Root",
             xml.Descendants("person").Select(
                 Function(p) New XElement("person",
                     New XAttribute("name", p.Element("name").Value),
                     p.Element("address").Value
                 )
             )
         )
MsgBox(q2.ToString())


投稿者 SSD   (社会人)   投稿日時 2022/6/22 17:22:48
魔界の仮面弁士 様
るきお 様

LINQが気持ち悪いと思っていた部分が語順以上に以下の違いなんだと気づきました。

<<SQL>>
Select [A], [B], [C]
From [Table]

<<LINQ>>
From [x] In [Collection]
Select [x].value

SQLではLINQの[x]に相当する部分が無く、とても違和感を感じていました。
でもよくよく考えたらSQLも以下と同じ意味合いだと気づきました。

Select [Row].[A], [Row].[B], [Row].[C]
From [Row] In [Table].Rows

LINQの[x]に該当するのがSQLのテーブルの各行であると考えたら
なんだか飲み込めるようになりました。
そう思うとFromとかWhereとかの語順が気にならなくなりました。

今のところ納得でき、クエリ構文も使えるようになりました。
ただ、内部結合・外部結合を使うようになった時にまた精神がやられそうな気がします。

投稿者 SSD   (社会人)   投稿日時 2022/6/22 17:26:16
魔界の仮面弁士 様

> XML が下火になってしまい
とのことですが、今はJSONが流行りですか?

投稿者 魔界の仮面弁士   (社会人)   投稿日時 2022/6/22 20:22:04
> でもよくよく考えたらSQLも以下と同じ意味合いだと気づきました。
> ただ、内部結合・外部結合を使うようになった時にまた精神がやられそうな気がします。

SQL で言うところの「テーブルの別名」に過ぎないですよ。

-- SQL
SELECT t.TeamID, t.TeamName, p.PersonID, p.Name
FROM Persons p INNER JOiN Teams p
  ON p.PersonID = t.PersonID


' LINQ クエリ構文 
Dim q1 = From p In PersonArray Join t In TeamArray
         On p.PersonID Equals t.PersonID
         Select t.TeamID, t.TeamName, p.PersonID, p.Name

' LINQ メソッド構文 
Dim q2 = PersonArray.Join(TeamArray,
         Function(p) p.PersonID,
         Function(t) t.PersonID,
         Function(p, t) New With {Key t.TeamID, t.TeamName, Key p.PersonID, p.Name})



> 今はJSONが流行りですか?
設定用の外部ファイルというと、昔は ini ファイルが使われていましたが、
Visual Studio の設定ファイルは XML になりました。そして
Visual Studio Code の設定では JSONC が利用されています。

JSON や JSONC が使われる機会は増えてきたと感じますが(稀に BSON)、
その他にも YAML などをしばしば見かけます。そのほかで有名どころは…TOML あたりでしょうか。


VB の XML リテラルのように、マークアップ言語をコンパイラレベルで盛り込んでしまうと、
後から直すのが面倒ですし、どこまでサポートすべきか見極めが難しくなりますので、
最近の C# (というか Roslyn のコードアナライザー)では、
こうした言語埋め込み機能を MEF によって外部から提供する方針をとっているようです。
https://docs.microsoft.com/ja-jp/dotnet/framework/mef/

たとえばこんな感じ。(VS2022 17.3.0 Preview 2.0)