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

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

新規登録して質問してみよう
ただいま回答率
85.46%
C#

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

Q&A

解決済

1回答

3324閲覧

C# 連番の振り直し方法について

---stax---

総合スコア148

C#

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

0グッド

0クリップ

投稿2021/09/09 03:46

初歩的な質問ですいません。
現在BlazorでToDoアプリを作成しています。
内容はDBに格納しており、以下のようにToDoの順番を表す番号と内容を要素として持っています。
1 洗濯
2 ゴミ捨て
3 買い出し
4 料理

やりたいことは要素を消した際に(例として2 ゴミ捨てを削除)、順番を表す番号を振りなおしたいと考えています。
1 洗濯            1 洗濯
2 ゴミ捨て          2 買い出し
3 買い出し          3 料理
4 料理            4 洗い物
5 洗い物           5 読書
6 読書

テーブルは以下の構成です

C#

1public partial class ToDoList 2{ 3 public int ToDoNum {get; set;} 4 public string ToDoText {get; set;} 5}

以下のように記述し、削除した次の要素のToDoNumだけ変更出来ましたが、

以下はUIで選択されたTodoの内容を受け取り、ToDoNumを変更しています。
削除した要素の番号は取得できるので(selectTodo)、削除された次の内容のToDoNumには+1しています。

C#

1// selectTodoはUIで選択されたTodoの内容 2public void ResettingToDoNumber(ToDoList selectTodo) 3{ 4  //削除した次の内容のToDoNumを設定 5  var nextNum = selectTodo.ToDoNum + 1; 6 7 using(var dbContext = DbFactory.CreateDbContext()) 8 { 9 //削除した次の内容を取得 10 var number = dbContext.ToDoList.Single(x => x.ToDoNum == nextNum); 11 12 //番号再設定 13 number.ToDoNum -= 1; 14 } 15}

しかし、残りの要素(上記での4~6)をどのように変更すればよいか思いつかず悩んでいます。
具体的には繰り返し処理をする必要があると考えますが、消された要素の後に、あと何個要素が残っているかをうまく表現できず悩んでいます。

試したこととして要素をカウントし、削除した要素からの差分をループカウンターに設定しようと考えましたが、
これでは残り何個としてうまく表現できませんでした。

c#

1//削除した次の内容のインデックスを設定 2var resettingNum = selectTodo.ToDoNum - 1; 3 4// 5var todoCount = dbContext.ToDoList.Count(); 6var remainingCount = todoCount - resettingNum;

とても回りくどいやり方をしているような気がします。
削除した要素以降の残りの要素の番号を振りなおすにはどのようにすればよいでしょうか?
初歩的な質問で申し訳ありませんがアドバイスいただきたいです。

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

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

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

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

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

gentaro

2021/09/09 04:42

そのToDoNumとやらをわざわざ振り直すのではなく、表示する時に上から順番に個別に番号振ればいいだけじゃ? 表示側のコードが示されてないからこれ以上は何ともだけど。
---stax---

2021/09/09 06:07

ありがとうございます。 確かに仰る通りです。複雑に考えていました。 削除した後に、Count()で全要素数が分かるのでそれで順番に振りなおすように試してみます。
退会済みユーザー

退会済みユーザー

2021/09/09 06:25

> 内容はDBに格納しており DB の構造はどうなっているのですか? 番号が主キーとかで、それを振り直すなんてことは 1 ミリも考えない方が良いと思いますよ。
BluOxy

2021/09/09 10:45 編集

個人的には、ToDoNum は表示するためだけにあるぐらいなら必要ないと思っています。 razorファイル側で処理すれば良いかと思います。 https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/build-a-blazor-app?view=aspnetcore-5.0&pivots=server Blazorを使ったことはないですが、上記を参考にすると下記のイメージです <ul> @foreach (var todo in todos.Select((v,i) => new { Value = v, Index = i})) { <li>@($"{todo.Index} - {todo.Value.ToDoText}")</li> } </ul>
---stax---

2021/09/09 14:20

BluOxy様 ありがとうございます。 恥ずかしながらforeachでインデックスも取得出来るのは初めて知りました。 確かにこのやり方なら別途処理を記述することなくhtml部分だけで完結できそうです。 今回は表示部分にはUIコンポーネントを使用しており、教えて頂いた記述方法は適応出来ないのですがとても参考になりました。 ありがとうございます。
guest

回答1

0

ベストアンサー

DB の構造はどうなっているのか不明ですが、もし番号 (ToDoNum) が主キーであれば、それを振り直すなんてことは 1 ミリも考えない方が良いと思いますよ。

EF Code First で DB を ToDoList クラスから DB 生成しているのではないかと想像していますが、そうであれば、例えば以下の Id のように、主キーは別に設けてはいかがですか? (主キーが無いと更新削除がままならないので必ず必要)

C#

1public class ToDoList 2{ 3 public int Id { get; set; } // 主キー 4 public int ToDoNum {get; set;} 5 public string ToDoText {get; set;} 6}

それをベースに EF Code First で DB を生成すれば Id という名前で SQL Server なら IDENTITY の主キー列が ToDoList テーブルにできるはずです。

ToDoNum は連番でなくても構わないので ToDo の順番だけ守って自由に設定してください。

そのうえでクエリに ORDER BY ToDoNum を含め、抽出するときに ToDoNum とは別に連番を振ってやれば望むことができると思います。

連番を振るのは SQL Server の SELECT クエリなら ROW_NUMBER が使えますが、Linq to Entities では別の手段が必要になります。

具体的な方法は以下の記事を見てください。

Generating Sequence Numbers In LINQ Query
https://coderethinked.com/generating-sequence-numbers-in-linq-query/

投稿2021/09/09 07:55

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

---stax---

2021/09/09 08:48

ありがとうございます。 情報が不足しており申し訳ございません。 テーブルに関してはId(主キー/自動発番)、ToDoNum(並べ替え専用)、ToDoTextの3つのカラムを所有しております。 今出先なのでコードが記載できませんが、ToDoの内容を削除後、要素数をカウントし、ループで回しながら1番から振りなおすというやり方を実施しました。 あまりいいやり方では無いように感じていたので教えていただいたリンクを参考にLINQでの連番付与も是非試してみます。 私はデータベースに関しても知識が乏しく初歩的な質問なのですが、今回ToDoの内容を削除する際は、レコードそのものを削除しています。 >> ToDo の順番だけ守って自由に設定してください この部分はレコードを削除するのではなく、Id列は残したまま、ToDoNumとToDoTextの内容だけUPDATEする、という意味でしょうか?(分かりにくくてすいません)
退会済みユーザー

退会済みユーザー

2021/09/09 09:29

> この部分はレコードを削除するのではなく、Id列は残したまま、ToDoNumとToDoTextの内容だけUPDATEする、という意味でしょうか?(分かりにくくてすいません) いえ、そういうことではないです。ToDo 項目そのものの削除は、質問者さんが行っているように、物理削除で良いと思います。「ToDo の順番だけ守って自由に設定」というのは、ToDoNum はどういう番号に設定してもいいので、抽出する際のクエリに ORDER BY ToDoNum を含めれば、抽出結果の ToDoText が期待する順番に並ぶようにするということです。
---stax---

2021/09/09 14:12

ありがとうございます。 内容理解出来ました。 私のやり方では1から振りなおしてるからその順に表示されるよね、という順番を制御しているようで出来ていないので、ORDER BYを含めたやり方に修正してみます。
退会済みユーザー

退会済みユーザー

2021/09/09 22:24

「番号」に代えて「何時何分」とするほうがいいかもしれません (ユーザーが設定するならその方がやり易いと思います)。とにかく、ORDER BY xxx で抽出結果の ToDoText が期待する順番に並べば良さそうです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問