回答編集履歴

5

脱字追加

2022/11/11 07:01

投稿

退会済みユーザー
test CHANGED
@@ -132,7 +132,7 @@
132
132
 
133
133
  > 自分が考えていたのは自分のサンプルのようにすでにDatatable型の表があって、それをクラス型のListに変えることが知りたかったですが、
134
134
 
135
- についても答えておきます。そんなことをするのに何の意味があるのかはなはだ疑問ではありますが・・・
135
+ についても答えておきます。そんなことをするのに何の意味があるのかは、はなはだ疑問ではありますが・・・
136
136
 
137
137
  質問欄下のコメント欄に書きましたが、DB のフィールドの NULL 可/不可によって考えなければならないことがあります。
138
138
 

4

訂正

2022/11/11 04:11

投稿

退会済みユーザー
test CHANGED
@@ -71,7 +71,7 @@
71
71
  }
72
72
  ```
73
73
 
74
- ** Category エンティティクラス**
74
+ **Category エンティティクラス**
75
75
 
76
76
  以下の画像の Categories テーブルに対応する Category クラス。
77
77
 

3

訂正

2022/11/11 03:53

投稿

退会済みユーザー
test CHANGED
@@ -128,7 +128,7 @@
128
128
 
129
129
  **【追記2】**
130
130
 
131
- 質問者さん、出てきたと思ったらまた去ってしまったようですが、の質問者さんのコメントの、
131
+ 質問者さん、出てきたと思ったらまた去ってしまったようですが、コメント欄の質問者さんのコメントの、
132
132
 
133
133
  > 自分が考えていたのは自分のサンプルのようにすでにDatatable型の表があって、それをクラス型のListに変えることが知りたかったですが、
134
134
 

2

追記2

2022/11/11 03:48

投稿

退会済みユーザー
test CHANGED
@@ -123,3 +123,78 @@
123
123
  > ・コードをキレイに実現したい
124
124
 
125
125
  ・・・を満足していると思いませんか?
126
+
127
+ ---
128
+
129
+ **【追記2】**
130
+
131
+ 質問者さん、出てきたと思ったらまた去ってしまったようですが、上の質問者さんのコメントの、
132
+
133
+ > 自分が考えていたのは自分のサンプルのようにすでにDatatable型の表があって、それをクラス型のListに変えることが知りたかったですが、
134
+
135
+ についても答えておきます。そんなことをするのに何の意味があるのかはなはだ疑問ではありますが・・・
136
+
137
+ 質問欄下のコメント欄に書きましたが、DB のフィールドの NULL 可/不可によって考えなければならないことがあります。
138
+
139
+ 上の Categories テーブルで言うと Description 列と Picture 列が NULL 可になっており、それに該当する Category クラスのプロパティの型がそれぞれ string? と byte[]? になっている点に注目してください。自力でクラスのコードを書く場合そこは自分で DB の NULL 可/不可を調べて書く必要があります。
140
+
141
+ それから、NULL がある場合、List<T> を作る元になる DataTable の当該セルがどうなるかにも要注意です。
142
+
143
+ 例えば、以下の画像のように Description 列に NULL が含まれている場合、
144
+
145
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-11-11/4174a106-212c-4afa-8d4a-de5793bb638a.jpeg)
146
+
147
+ SqlDataAdapter で作成した DataTable では当該セルには DBNull.Value が入ります。
148
+
149
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-11-11/c5478808-7e51-421a-886a-2f543da2e583.jpeg)
150
+
151
+ なので、DataRow["Description"] で取得したセルのデータを string にキャスト(=ボックス化解除)すると DBNull.Value が入っている場合はエラーになります。
152
+
153
+ Zuishin さんが質問のコメントで提案されている DataRowExtensions.Field メソッドはそのあたりには対応しているようで、DBNull.Value が入っている場合は null を返してくれます。
154
+
155
+ というわけで、上の Categories テーブルから SqlDataAdapter で DataTable を作成し、それから List<Category> 型のオブジェクトを作るなら以下のようにするのが良さそうです。Visual Studio で .NET 6.0 のプロジェクトを作るとデフォルトで NULL 許容参照型が有効になりますので、その対応も考える必要があります。
156
+
157
+ ```C#
158
+ using System.Data;
159
+ using System.Data.SqlClient;
160
+
161
+ var selectQuery = "SELECT [CategoryID],[CategoryName],[Description],[Picture] FROM [Categories]";
162
+ var connString = "・・・接続文字列・・・";
163
+ var table = new DataTable();
164
+ using (var connection = new SqlConnection(connString))
165
+ {
166
+ using (var command = new SqlCommand(selectQuery, connection))
167
+ {
168
+ var adapter = new SqlDataAdapter(command);
169
+ adapter.Fill(table);
170
+ }
171
+ }
172
+
173
+ var list = table.AsEnumerable()
174
+ .Select(row => new Category {
175
+ CategoryId = row.Field<int>("CategoryID"),
176
+ CategoryName = row.Field<string>("CategoryName")!,
177
+ Description = row.Field<string>("Description"),
178
+ Picture = row.Field<byte[]>("Picture")
179
+ })
180
+ .ToList();
181
+
182
+ foreach(var c in list)
183
+ {
184
+ Console.WriteLine($"ID: {c.CategoryId}, Name: {c.CategoryName}, " +
185
+ $"Description: {c.Description ?? "null が入ってます"}");
186
+ }
187
+
188
+
189
+ public class Category
190
+ {
191
+ public int CategoryId { get; set; }
192
+ public string CategoryName { get; set; } = null!;
193
+ public string? Description { get; set; }
194
+ public byte[]? Picture { get; set; }
195
+ }
196
+ ```
197
+
198
+ 結果は以下のようになります。
199
+
200
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-11-11/465c98c7-4bed-4ea4-843e-bb2a7cad2282.jpeg)

1

追記

2022/11/10 07:03

投稿

退会済みユーザー
test CHANGED
@@ -4,3 +4,122 @@
4
4
 
5
5
  なければ Visual Studio の ADO.NET Entity Data Model ウィザードを使って Entity Data Model を生成して、それをベースに Linq to Entities で List<ItemModel> 型のオブジェクトを取得してはいかがですか?
6
6
 
7
+ ---
8
+
9
+ **【追記】**
10
+
11
+ 質問者さんはこちらの質問に答えないで去ってしまったようなのでいろいろ不明ですが、DataTable を経由しなければならない理由はないと理解して、
12
+
13
+ > 例でもよいのでサンプルコードを書いてくれますか?
14
+
15
+ ・・・に答えて Linq to Entities で List<T> 型のオブジェクトを取得するやり方を以下に書いておきます。
16
+
17
+ .NET 6.0 だそうですので EF Core を使うことになりますが、EF Core では ADO.NET Entity Data Model ウィザードは使えないので、リバースエンジニアリングという方法でコンテキストクラスとエンティティクラスを作ります。
18
+
19
+ 詳しい方法は以下の記事を見てください。
20
+
21
+ リバース エンジニアリング
22
+ https://learn.microsoft.com/ja-jp/ef/core/managing-schemas/scaffolding/?tabs=dotnet-core-cli
23
+
24
+ Scaffold-DbContext
25
+ https://learn.microsoft.com/en-us/ef/core/cli/powershell#scaffold-dbcontext
26
+
27
+ Microsoft のサンプル SQL Server データベース Northwind をリバースエンジニアリングすると、以下のようなコードが自動生成されます。**自力でコードを書く必要はありません**。
28
+
29
+ **NorthwindContext コンテキストクラス**
30
+
31
+ ```C#
32
+ using System;
33
+ using System.Collections.Generic;
34
+ using Microsoft.EntityFrameworkCore;
35
+ using Microsoft.EntityFrameworkCore.Metadata;
36
+ using MvcCore6App2.Models;
37
+
38
+ namespace MvcCore6App2.Data
39
+ {
40
+ public partial class NorthwindContext : DbContext
41
+ {
42
+ public NorthwindContext()
43
+ {
44
+ }
45
+
46
+ public NorthwindContext(DbContextOptions<NorthwindContext> options)
47
+ : base(options)
48
+ {
49
+ }
50
+
51
+ public virtual DbSet<Category> Categories { get; set; } = null!;
52
+ public virtual DbSet<Customer> Customers { get; set; } = null!;
53
+ public virtual DbSet<Employee> Employees { get; set; } = null!;
54
+ public virtual DbSet<Order> Orders { get; set; } = null!;
55
+ public virtual DbSet<OrderDetail> OrderDetails { get; set; } = null!;
56
+ public virtual DbSet<Product> Products { get; set; } = null!;
57
+ public virtual DbSet<Shipper> Shippers { get; set; } = null!;
58
+ public virtual DbSet<Supplier> Suppliers { get; set; } = null!;
59
+
60
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
61
+ {
62
+ if (!optionsBuilder.IsConfigured)
63
+ {
64
+ optionsBuilder.UseSqlServer("・・・接続文字列・・・");
65
+ }
66
+ }
67
+
68
+ // ・・・中略・・・
69
+
70
+ }
71
+ }
72
+ ```
73
+
74
+ ** Category エンティティクラス**
75
+
76
+ 以下の画像の Categories テーブルに対応する Category クラス。
77
+
78
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-11-10/b3913979-89a3-4e55-9e19-eea4376f0c56.jpeg)
79
+
80
+ ```C#
81
+ using System;
82
+ using System.Collections.Generic;
83
+ using System.ComponentModel.DataAnnotations;
84
+ using System.ComponentModel.DataAnnotations.Schema;
85
+ using Microsoft.EntityFrameworkCore;
86
+
87
+ namespace MvcCore6App2.Models
88
+ {
89
+ [Index("CategoryName", Name = "CategoryName")]
90
+ public partial class Category
91
+ {
92
+ public Category()
93
+ {
94
+ Products = new HashSet<Product>();
95
+ }
96
+
97
+ [Key]
98
+ [Column("CategoryID")]
99
+ public int CategoryId { get; set; }
100
+ [StringLength(15)]
101
+ public string CategoryName { get; set; } = null!;
102
+ [Column(TypeName = "ntext")]
103
+ public string? Description { get; set; }
104
+ [Column(TypeName = "image")]
105
+ public byte[]? Picture { get; set; }
106
+
107
+ [InverseProperty("Category")]
108
+ public virtual ICollection<Product> Products { get; set; }
109
+ }
110
+ }
111
+ ```
112
+
113
+ 上の NorthwindContext コンテキストクラスと Category エンティティクラスを使えば、以下の 2 行で SQL Server の Categories テーブルのレコードすべてを List<Category> 型のオブジェクトとして取得できます。
114
+
115
+ ```
116
+ NorthwindContext context = new NorthwindContext();
117
+ List<Category> list = context.Categories.ToList();
118
+ ```
119
+
120
+ 質問者さんのやりたいこと、
121
+
122
+ > ・.ToList()みたいにDataTableのデータ全体をList型にできないか
123
+ > ・コードをキレイに実現したい
124
+
125
+ ・・・を満足していると思いませんか?