ネットが遅くてイライラしてない!?

VB2017.Netで、DataTableでLINQを使いたいと考えています。
仮に、下記のコードを実行すると、メッセージボックスに山田と表示されます。
(質問1)
フォームにTextBoxを置いて、TextBoxの入力内容に従って、”1944”と”1959”を切り替えるLINQはどのように書けばよろしいのでしょうか?
(質問2)
Select句で、”IN0020”と”IN0015”の列を取得するには、Select句をどのように記述すればよろしいでしょうか?(dtcode("IN0020"),dtcode("IN0020")とするとエラーになる)
(質問3)
EnumerableRowCollection(Of Object) は、EnumerableRowCollection(Of DataRow)とするとエラーになります。マイクロソフトのHPでは、Public Function AsEnumerable (source As DataTable) As EnumerableRowCollection(Of DataRow)となっていますが、エラーになる理由はなんでしょうか?

https://docs.microsoft.com/ja-jp/dotnet/api/syst …

詳しい方宜しくお願い致します。

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim Dt As New DataTable
Dim Dc As DataColumn
Dc = New DataColumn
Dc.ColumnName = "IN0010"
Dt.Columns.Add(Dc)
Dc = New DataColumn
Dc.ColumnName = "IN0015"
Dt.Columns.Add(Dc)
Dc = New DataColumn
Dc.ColumnName = "IN0020"
Dt.Columns.Add(Dc)

Dt.Rows.Add({1944, 107, "山田"})
Dt.Rows.Add({1959, 109, "林"})

Dim tmp As EnumerableRowCollection(Of Object) = From dtcode In Dt.AsEnumerable()
Where dtcode("IN0010") = "1944"
Select dtcode("IN0020")

MsgBox(tmp(0).ToString)

End Sub

A 回答 (3件)

(回答1)


「フォームにTextBoxを置いて、TextBoxの入力内容に従って、”1944”と”1959”を切り替える」
の意味をもっと具体的に書いてください。

Dt.Rows.Add({1944, 107, "山田"})
Dt.Rows.Add({1959, 109, "林"})

Dt.Rows.Add({1959, 107, "山田"})
Dt.Rows.Add({1944, 109, "林"})
にしたいということですか?

Where dtcode("IN0010") = "1944"

Where dtcode("IN0010") = "1959"
にしたいということですか?

いずれも、直接書いてある箇所を、変数なりなんなりに変えればできます。


(回答2)
(回答3)
まず、
Public Function AsEnumerable (source As DataTable) As EnumerableRowCollection(Of DataRow)
が適用されるのは
Dt.AsEnumerable()
だけです。

対して
Dim tmp As EnumerableRowCollection(Of Object) = From dtcode In Dt.AsEnumerable()
Where dtcode("IN0010") = "1944"
Select dtcode("IN0020")

というプログラムで 変数tmpに入れようとしているのは
From dtcode In Dt.AsEnumerable()
Where dtcode("IN0010") = "1944"
Select dtcode("IN0020")

という式(の評価結果)です。ここまでで1つです。
Public Function AsEnumerable() の戻り値は関係ありません。


https://docs.microsoft.com/ja-jp/dotnet/visual-b …

ここをよく読むとわかるのですが

Select では
・1つだけ値を指定したら、その型
・カンマ区切りで複数指定したり、列の別名を指定したりすると「匿名型」
のIEnumerable(of T)を返します。
(細かくは違うところもあるかもしれませんが)

Select dtcode("IN0020")
の場合、
・dtcodeはDataRow型→ dtcode(列) は Object型
なので、このSelectにより IEnumerable(Of Object) が返ります。
※ 実体は EnumerableRowCollection(Of Object) かもしれませんが

「dtcode("IN0020"),dtcode("IN0020")とするとエラーになる」
のは、
> var1
> 任意。 列式の結果を参照するために使用できる別名。
にあたる部分を推測できなかったためのものでしょう。
先のマニュアルの例では
Select product.ProductName → ProductName という列名
といった推測ができます。

よって、解決策の一つは「列名となるものを指定する」です。

ただ
Option Strict Off や Option Infer On の状態なら、匿名型の扱いも楽なのですが、
Option Strict On, Option Infer Off の状態だと、匿名型を使うのが面倒です。


なので、もう一つの方法「Select で一つの値だけを指定する」を使うのがよいでしょう。
複数の値を使いたいなら、それを一つにまとめるような仕組みを使います。
・dtcode は(複数の値をまとめた)DataRow型です。Select dtcode で IEnumerable(Of DataRow)になります
・Tuple(of 〜)も即席のクラスを作るのに便利です。
・同じ型だけを使うのなら、配列も使えます。
・面倒ですが、(専用に作った)クラス/構造体も使えます。
    • good
    • 2
この回答へのお礼

ご返答有難うございました。
知りたいことが、全て記載されています。
熟読して、自分のものにしていきたいと思います。

有難うございました。

お礼日時:2020/07/29 08:27

詳しい訳ではないです。


やってみて結果が出たら『あら不思議』な初級レベルのオッサンです。

Dim tmp As EnumerableRowCollection(Of DataRow) = From dtcode In Dt.AsEnumerable()
Where dtcode("IN0010") = TextBox1.Text
Select dtcode

MsgBox(String.Join("_", New String() {tmp(0)("IN0010").ToString, tmp(0)("IN0015").ToString, tmp(0)("IN0020").ToString}))

Console.WriteLine(String.Join("=", New String() {tmp(0)(0).ToString, tmp(0)(1).ToString, tmp(0)(2).ToString}))

出力結果:
1944=107=山田
    • good
    • 0
この回答へのお礼

有難うございました。

お礼日時:2020/07/29 08:28

質問1だけ


Where dtcode("IN0010") = "1944" と書いている行の"1944"を変数として、その中の値を"1959"に変えてあげればうまくいくかも?

私は、C#をメインに使っていますし、LINQでDB検索する場合には質問にあるようなSQL形式ではなくて、メソッド形式を使うことが多いので、質問2,3は分からないのですけどね。

ちなみに、最新のASP.NET Core BlazorではVB.NETはサポートされず、C#かF#だけになったようなので、C#をメインにされるほうがいいかもしれませんね。
    • good
    • 0
この回答へのお礼

有難うございました。

お礼日時:2020/07/29 08:28

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング