質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
DTO(Data Transfer Object)

DTO(Data Transfer Object)とは、データを転送するために定義されたクラスのこと。関連データを集約し、データの格納や読み出しのメソッドを定義したオブジェクトです。データを管理するためのフィールド群に対応したセッター・ゲッターで構成されています。

DAO(Data Access Object)

DAO(Data Access Object)とは、データベースなどに保存するための操作を実装したオブジェクトのことです。データの永続化機構に抽象化されたインタフェースを提供し、データベースの詳細を隠蔽。ビジネスロジックとデータ操作も分離できます。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

2回答

5456閲覧

VB.net Dtoの詰め替えで効率の良い方法が分からない

tk68716

総合スコア24

DTO(Data Transfer Object)

DTO(Data Transfer Object)とは、データを転送するために定義されたクラスのこと。関連データを集約し、データの格納や読み出しのメソッドを定義したオブジェクトです。データを管理するためのフィールド群に対応したセッター・ゲッターで構成されています。

DAO(Data Access Object)

DAO(Data Access Object)とは、データベースなどに保存するための操作を実装したオブジェクトのことです。データの永続化機構に抽象化されたインタフェースを提供し、データベースの詳細を隠蔽。ビジネスロジックとデータ操作も分離できます。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2021/06/10 09:01

編集2021/06/14 00:17

バージョン VB.net 4.5.2

閲覧ありがとうございます。
単票形式の帳票で12件ずつのデータを出力します。
Daoで取得したDataTableをFoeRoopでDtoに詰め替えるのですが
どうしてもコードが冗長になるので、もっとスッキリ書ける方法はないかアドバイスを頂きたいです。

DTOクラス

VB

1 2Class RPT_0060SettingDto 3 4 Public Property biz As String 5 Public Property rack_id As String 6 7 Public Property disp_color_1 As String 8 Public Property parts_no_1 As String 9 Public Property name_1 As String 10 Public Property parts_name_1 As String 11 Public Property location_no_1 As String 12 Public Property order_point_1 As String 13 14 Public Property disp_color_2 As String 15 Public Property parts_no_2 As String 16 Public Property name_2 As String 17 Public Property parts_name_2 As String 18 Public Property location_no_2 As String 19 Public Property order_point_2 As String 20 21 'プロパティが連番で12まで続く・・・ 22 23 Public Property disp_color_12 As String 24 Public Property parts_no_12 As String 25 Public Property name_12 As String 26 Public Property parts_name_12 As String 27 Public Property location_no_12 As String 28 Public Property order_point_12 As String 29 30End Class 31 32

問題のコード

VB

1Class RPT_0060Util 2 3 Shared Function GetSettingDto(ByVal table As DataTable) As List(Of RPT_0060SettingDto) 4 5 Dim dtoList As New List(Of RPT_0060SettingDto) 6 Dim settingDto As RPT_0060SettingDto 7 8 Dim i As Integer = 0 9 10 For Each row As DataRow In table.Rows 11 '改ページしたら初期化 12 If i > 0 And i Mod 12 = 0 Then 13 dtoList.Add(settingDto) 14 settingDto = New RPT_0060SettingDto 15 End If 16 17 18 If i Mod 12 = 0 Then 19 settingDto.disp_color_1 = row("disp_color").ToString 20 settingDto.parts_no_1 = row("parts_no").ToString 21 settingDto.parts_name_1 = row("parts_name").ToString 22 settingDto.location_no_1 = row("location_no").ToString 23 settingDto.order_point_1 = row("order_point").ToString 24 ElseIf i Mod 12 = 1 Then 25 settingDto.disp_color_2 = row("disp_color").ToString 26 settingDto.parts_no_2 = row("parts_no").ToString 27 settingDto.parts_name_2 = row("parts_name").ToString 28 settingDto.location_no_2 = row("location_no").ToString 29 settingDto.order_point_2 = row("order_point").ToString 30 End If 31 32 i = i + 1 33 Next 34 dtoList.Add(settingDto) 35 36 Return settingDto 37 38 End Function 39 40End Class

DTOのプロパティが1から12までの連番になっているので
settingDto.disp_color_ + 変数・・・で取得できそうなのですがうまくいきませんでした。
何か良い方法をご教授いただけると助かります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/06/10 20:20 編集

RPT_0060SettingDto クラスの構造を大幅に見直すことはできるのですか? それができないと「どうしてもコードが冗長」というところはほとんど改善の余地はなさそうです。 大幅に変更できる、例えば、12 レコードの配列もしくは List<レコード> を RPT_0060SettingDto の要素にするよう見直すことができるなら、Linq to Enitities / Objects の Skip, Take とかを使えばかなりスマートにできそうな気がしますけど。
退会済みユーザー

退会済みユーザー

2021/06/10 23:53

VBタグはこのサイトだとVB6以下を指し、VB.NETは機能・文法的にも別物になっているので、VBタグは削除してください。
退会済みユーザー

退会済みユーザー

2021/06/12 00:32

質問者さん、無言ですが、回答が付いているのでそれらに対するフィードバックを書いてください。役に立った / 立たなかったぐらいはすぐ返せるのでは? 役に立たなかったならどこがダメだったかを書くとより期待に近い回答が出てくるかも。とにかく無言で放置は NG です。
tk68716

2021/06/12 03:14

皆様ご回答ありがとうございます。 休暇を取っていたもので回答に対する返答が遅れました。 Suferさんの回答の通り、Dtoの構造を見直してみようと思います。
退会済みユーザー

退会済みユーザー

2021/06/15 22:24 編集

その後どうなったのか進展を書いてください。 問題・課題が解決できたのであればベストアンサーを選んでこのスレッドはクローズしてください。 いつまでも無言で放置はしないようお願いします。
guest

回答2

0

どうしてもコードが冗長になるので、もっとスッキリ書ける方法はないかアドバイスを頂きたいです。

質問のコメント欄に書きましたが、RPT_0060SettingDto クラスの構造を大幅に見直さないと「どうしてもコードが冗長」というところはほとんど改善の余地はなさそうです。

なので、質問者さんのケースで DTO をどのように処置しているか不明なので可能かどうかわかりませんが、12 レコードの List<レコード> を RPT_0060SettingDto の要素にするよう見直して、Linq to Enitities の Skip, Take を使って取得する方法を提案しておきます。結果は radian が提案されたものとほぼ同じになるようですが。

実際にできるところを示さないと説得力がないかもしれませんが、質問者さんのデータソースは使えませんので、Microsoft のサンプルデータベース Northwind の Products テーブルを使います。内容は以下の通りで 77 レコードあります。

イメージ説明

DTO は以下のようにします。以下 C# で書きますが読めますよね? ダメなら変換サービス https://converter.telerik.com/ がありますので使ってみてください。

public class ProdtctDTO { public int ProductID { get; set; } public string ProductName { get; set; } public Nullable<decimal> UnitPrice { get; set; } } public class RPT_0060SettingDto { public string Biz { get; set; } public string RackId { get; set; } // これに 12 レコード取得する public List<ProdtctDTO> ProductList { get; set; } }

まず、SQL Server から直接 Linq to Entities で取得するコードは以下の通りです。NORTHWINDEntities というのは、Visual Studio の ADO.NET Entity Data Model ウィザードを使って自動生成させた EDM のコンテキストクラスです。

using System; using System.Collections.Generic; using System.Linq; using System.Data; using System.Data.SqlClient; namespace ConsoleAppLinqToEntities { class Program { static void Main(string[] args) { // Linq to Entities で SQL Server から直接取得 List<RPT_0060SettingDto> list = new List<RPT_0060SettingDto>(); NORTHWINDEntities context = new NORTHWINDEntities(); // レコード総数 int count = context.Products.Count(); // 12 件ずつ int pageSize = 12; // list の中の RPT_0060SettingDto の数 int totalPages = (int)Math.Ceiling(count / (double)pageSize); for (int i = 0; i < totalPages; i++) { RPT_0060SettingDto settingDto = new RPT_0060SettingDto(); settingDto.Biz = "Product-" + i; settingDto.RackId = i.ToString(); IQueryable<ProdtctDTO> productList = context.Products .OrderBy(p => p.ProductID) .Skip(i * pageSize) .Take(pageSize) .Select(p => new ProdtctDTO { ProductID = p.ProductID, ProductName = p.ProductName, UnitPrice = p.UnitPrice }); settingDto.ProductList = productList.ToList(); list.Add(settingDto); } } } }

結果は以下のようになります。期待通り取得できているのが分かるでしょうか? ただ、一つだけ余計な点があって、それは、for ループで回すたびに SQL Server にクエリを投げてレコードを取得する点です。なので、context.Products.ToList() でまず全レコード取得してから目的の形に加工した方が良いかもしれません。

イメージ説明

どうしても DataTable を使いたいという場合は、以下のようにして同じ結果を取得できます。

// 一旦 SQL Server から DataTable にレコードを取得し、それから目的のリストを取得 List<RPT_0060SettingDto> list2 = new List<RPT_0060SettingDto>(); // SQL Server からレコードを取得し DataTable を作成 DataTable table = new DataTable(); string connString = Properties.Settings.Default.NORTHWINDConnectionString; string selectQuery = "SELECT * FROM [Products]"; using (var connection = new SqlConnection(connString)) { var adapter = new SqlDataAdapter(); using (var command = new SqlCommand(selectQuery, connection)) { adapter.SelectCommand = command; adapter.Fill(table); } } for (int i = 0; i < totalPages; i++) { RPT_0060SettingDto settingDto = new RPT_0060SettingDto(); settingDto.Biz = "Product-" + i; settingDto.RackId = i.ToString(); IEnumerable<ProdtctDTO> productList = table.AsEnumerable() .OrderBy(p => p.Field<int>("ProductID")) .Skip(i * pageSize) .Take(pageSize) .Select(p => new ProdtctDTO { ProductID = p.Field<int>("ProductID"), ProductName = p.Field<string>("ProductName"), UnitPrice = p.Field<decimal?>("UnitPrice") }); settingDto.ProductList = productList.ToList(); list2.Add(settingDto); }

投稿2021/06/11 02:29

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

12まで続くプロパティの部分を別クラスにして、それでList作ったらどうでしょう。
例えば、

vbnet

1 Class Hoge 2 Public Sub New(row As DataRow) 3 disp_color = row("disp_color").ToString 4 parts_no = row("parts_no").ToString 5 parts_name = row("parts_name").ToString 6 location_no = row("location_no").ToString 7 order_point = row("order_point").ToString 8 End Sub 9 10 Public Property disp_color As String 11 Public Property parts_no As String 12 Public Property name As String 13 Public Property parts_name As String 14 Public Property location_no As String 15 Public Property order_point As String 16 End Class

こんなクラスを作って、

vbnet

1 settingDto = New RPT_0060SettingDto 2 dtoList.Add(settingDto) 3 For Each row As DataRow In table.Rows 4 If settingDto.HogeList.Count = 12 Then 5 settingDto = New RPT_0060SettingDto 6 dtoList.Add(settingDto) 7 End If 8 9 settingDto.HogeList.Add(New Hoge(row)) 10 Next

こんな感じのループにすると、HogeListが12個溜まった次のループでdtoListが追加されます。
(適当に考えたので、デバッグはしてないです)

投稿2021/06/10 10:04

編集2021/06/10 10:28
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tk68716

2021/06/12 03:16

ご回答ありがとうございます。 こちらの方法も試してみます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問