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

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

新規登録して質問してみよう
ただいま回答率
85.48%
.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

Q&A

解決済

1回答

1226閲覧

Linqを使ったデータ抽出方法

zerokuro

総合スコア1

.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

0グッド

0クリップ

投稿2020/10/25 09:43

前提・実現したいこと

初めて質問させていただきます。

データを削除する際に、削除してもOKかを確認するためのチェック処理にて
どのようにデータを抽出すればしたいことが実現できるのか行き詰ってしまいました。

次のようなマスタ同士を紐付けするテーブルがあります。

マシンID分類ID
マシンA分類1
マシンB分類2
マシンC分類2
マシンB分類3
マシンC分類3
マシンC分類4

マシンは複数の分類に所属できるようなイメージです。
ただし、ルールとしてマシンは必ずどこかの分類に所属しなければいけません。

この状態で分類3を削除しようとした場合(実際には削除フラグを立てる)
分類3に所属するマシンBおよびマシンCは、それぞれ別の分類にも所属しているため
問題なく分類3は削除できます。

しかし、分類2と分類3を同時に削除しようとした場合
マシンCは分類4に所属しているため問題ないですが
マシンBはどこにも所属しなくなってしまうため、エラーとする必要があります。
かつ、エラーメッセージ内にどの分類が削除できないのかを表示したいです。
「分類に所属しないマシンが発生するため、削除できません。対象分類:{0}」 ←複数あればカンマ区切りで表示

このようなことがしたいのですが、上手くデータを引っ張ってくる方法が思いつきません。

わかりにくくて申し訳ございませんが、方向性だけでもご助言いただけますと助かります。
よろしくお願い致します。

該当のソースコード

C#

1 public string CheckHimoduke(DbContext db, ViewModel model) 2 { 3 var result = string.Empty; 4 5 // 廃止対象となる小分類 6 var haishiBunrui = new string[] { "分類2", "分類3" }; 7 8 9 // 廃止対象の分類に紐づいている情報を取得する 10 var himoduke = (from A in db.bunrui_himoduke 11 .Where(x => haishiBunrui.Contains(x.bunrui_cd)) 12 from B in db.bunrui_himoduke 13 .Where(x => x.machine_cd == A.machine_cd) 14 select new 15 { 16 B.machine_cd, 17 B.bunrui_cd, 18 } 19 ).Distinct(); 20 21      // 上で取得できるデータ 22      // [0]:{machine_cd="マシンA", bunrui_cd="分類2"} 23      // [1]:{machine_cd="マシンA", bunrui_cd="分類3"} 24      // [2]:{machine_cd="マシンB", bunrui_cd="分類2"} 25      // [3]:{machine_cd="マシンB", bunrui_cd="分類3"} 26      // [4]:{machine_cd="マシンB", bunrui_cd="分類4"} 27 28 // 上記のうち、廃止対象外の分類にも紐づいているマシンを取得する 29 var test = from A in himoduke 30 .Where(x => !haishiBunrui.Contains(x.bunrui_cd)) 31 select A; 32 33      // 上で取得できるデータ 34      // [0]:{machine_cd="マシンB", bunrui_cd="分類4"} 35 36 37 // ここにきてどうしたらいいのかわからなくなってしまった。。 38 39 40 // エラーとなる分類を羅列して返したい(今回の場合 "分類2") 41 return result; 42 }

補足情報(FW/ツールのバージョンなど)

C#
.NET Core3.1

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

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

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

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

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

gentaro

2020/10/25 13:30

> しかし、分類2と分類3を同時に削除しようとした場合 1個ずつ処理すりゃいいんじゃないの? なんでやり方がわからないのに、問題を難しく解決しようとするのかわからない。
hihijiji

2020/10/26 01:44

世の中には定石と言うものがあります。 貴方が考えた特別な方法は、あなた一人だけにしか分かりません。 定石を知るには、"RDB 多対多"で検索して、上位5サイトほど眺めてください。 私がググった中では上位サイトでも間違った説明をしている部分が あったので複数のサイトを参考にすることをお勧めします。
Zuishin

2020/10/26 03:25

削除する分類に属するマシンの集合から、削除しない分類に属するマシンの集合を Except すればいいと思います。そうすれば生成される SQL は一行で済み、パフォーマンスが良いのではないでしょうか。Contains と not Contains が使えます。
guest

回答1

0

ベストアンサー

Formアプリでサンプル書いてみました。
全部LINQにする必要はないと思います。

C#

1 private void Test() 2 { 3 //テストデータ準備 4 var db = new List<bunrui_himoduke>(); 5 db.Add(new bunrui_himoduke { machine_cd = "マシンA", bunrui_cd = "分類1" }); 6 db.Add(new bunrui_himoduke { machine_cd = "マシンB", bunrui_cd = "分類2" }); 7 db.Add(new bunrui_himoduke { machine_cd = "マシンC", bunrui_cd = "分類2" }); 8 db.Add(new bunrui_himoduke { machine_cd = "マシンB", bunrui_cd = "分類3" }); 9 db.Add(new bunrui_himoduke { machine_cd = "マシンC", bunrui_cd = "分類3" }); 10 db.Add(new bunrui_himoduke { machine_cd = "マシンC", bunrui_cd = "分類4" }); 11 12 var haishiBunrui = new List<string>() { "分類2", "分類3" }; 13 14 //テスト結果の準備 15 var result = db.Select(x => new Result { machine_cd = x.machine_cd, bunrui_cd = x.bunrui_cd, delete = false } ).ToList(); 16 17 //削除対象をマークする 18 foreach (var y in result.Where(y => haishiBunrui.Any(x => y.bunrui_cd == x))) 19 { 20 y.delete = true; 21 } 22 23 //テスト 24 foreach( var g in result.GroupBy(g => g.machine_cd)) 25 { 26 if(g.All(x => x.delete == true)) 27 { 28 Console.WriteLine($"マシンコード({g.Key})は削除できません。"); 29 var 分類 = g.Select(y => y.bunrui_cd).ToList(); 30 Console.WriteLine($"対象分類は({string.Join(",", 分類)})"); 31 } 32 } 33 }

無理やりLINQ使ってみた。

C#

1 var test = db.Select(y => haishiBunrui.Any(x => y.bunrui_cd == x) 2 ? new Result { machine_cd = y.machine_cd, bunrui_cd = y.bunrui_cd, delete = true } 3 : new Result { machine_cd = y.machine_cd, bunrui_cd = y.bunrui_cd, delete = false }) 4 .GroupBy(g => g.machine_cd); 5 6 //テスト 7 foreach (var g in test) 8 { 9 if (g.All(x => x.delete == true)) 10 { 11 Console.WriteLine($"マシンコード({g.Key})は削除できません。"); 12 var 分類 = g.Select(y => y.bunrui_cd).ToList(); 13 Console.WriteLine($"対象分類は({string.Join(",", 分類)})"); 14 } 15 }

投稿2020/10/26 02:20

編集2020/10/26 03:57
kikukiku

総合スコア514

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

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

zerokuro

2020/11/01 22:44

お返事遅くなり大変申し訳ございません。 サンプルまで書いていただきありがとうございます。 とても助かりました。 削除対象をマークする用のフラグを設けるなど、まったく頭になかったためとても勉強になりました。 また、AllやAnyの使い方がまだまだわかってないなと痛感しました… コメントいただきました皆様もありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問