DataTableで採番するには?

解決


Franz  2008-04-05 11:48:27  No: 144603  IP: 192.*.*.*

お世話になります。
VB2005EE, XPで、データベースアプリを作成しています。
DataTableに新規レコードを追加する場合、
主キーの採番方法がよくわかりません。
ヒントをいただけると幸いです。よろしくお願いします。

編集 削除
やじゅ  2008-04-06 00:38:10  No: 144604  IP: 192.*.*.*

微妙に違うかも知れませんが、
AutoIncrementプロパティ

新しい行が追加されたときに列値が自動的にインクリメント
http://dobon.net/vb/dotnet/datagrid/autoincrement.html

編集 削除
Franz  2008-04-06 19:22:29  No: 144605  IP: 192.*.*.*

すいません、説明不足ですね。
質問が的外れだったらごめんなさい。
データベース(ID, Name)はIDを主キーとします。
DataTableにデータを抽出します。
ListBoxにDataTableを連結します。
ListBoxに項目を追加する場合、DataTableに追加するとListBoxに反映されることを確認しました。
ただ、そのDataTableをデータベースに反映させる場合、主キーの重複でエラーがでないように、
と考え、上手な採番方法を考えています。
いかがなものでしょう、よろしくお願いします。

編集 削除
YuO  2008-04-06 23:19:10  No: 144606  IP: 192.*.*.*

主キーとは採番するものではありません。
# 採番する「場合もある」かもしれませんが。
個々のシステムによって,方法は変化します。

そのテーブルに行を追加するSQLはどのようになりますか。
そのSQLを,テーブルアダプタのInsertCommandに指定してやれば,基本的に処理出来るはずです。
# オブジェクトの値を設定し直す必要はあるでしょうが。

編集 削除
Franz  2008-04-07 10:26:01  No: 144607  IP: 192.*.*.*

YuOさん、ありがとうございます。
ただ、まだあまりよくわかっておりません。
もう少しアドバイスお願いします。

'フォームにListBox1, Button1, Button2を用意します。
'ListBox1(Table)に追加
Private Sub Button1_Click(...) Handles Button1.Click
Dim Table As DataTable = DirectCast(ListBox1.DataSource, DataTable)
Table.Rows.Add(5, "aaa")
'←この部分の追加方法を考えています。
End Sub

'データベースへ反映
Private Sub Button2_Click(...) Handles Button2.Click
Dim Cn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;...")
Dim SQLCm As OleDbCommand = Cn.CreateCommand
Dim Table As DataTable = DirectCast(ListBox1.DataSource, DataTable)
For Each Row As DataRow In Table.Rows
Dim SQL As String = ""
If Row.RowState = DataRowState.Added then
SQLCm.CommandText = "INSERT INTO GroupTable VALUES (" & Row("GroupID") & ", " & "'" & Row("Group") & "')"
Cn.Open()
SQLCm.ExecuteNonQuery()
Cn.Close()
End If
Next
End Sub

Button1によりListBox1(Table)に追加し、Button2でデータベースに反映させる感じです。
そもそも考え方から間違っているのであればすいません。
よろしくお願いします。

編集 削除
YuO  2008-04-08 12:19:35  No: 144608  IP: 192.*.*.*

で,IDとして使う値は,どのように決めているのですか?
これはあくまでシステムの問題ですから,Franzさん以外に答えられる人はいません。
# Franzさんの扱うシステムを知っている人がいるなら別ですが。

コードを見る限り5固定ですが,これでは主キー制約に違反します。

編集 削除
Franz  2008-04-08 12:50:55  No: 144609  IP: 192.*.*.*

すいません。それを質問したかったのです。
IDとして使う値を決める方法として効率よい方法があればお聞きしたいと思っていました。
もちろん5では制約違反です。
制約違反にならない、'5'を決める方法を考えています。
いろいろ調べる中で、データベースからIDの最大値をとり、
+1した値を使う方法は何とかできました。
この決め方でよいのか、また、その他に良い方法があるのかがわかりません。
もう少しアドバイスお願いします。

編集 削除
魔界の仮面弁士  2008-04-08 13:23:53  No: 144610  IP: 192.*.*.*

どのデータベースを使っているのかによっても変わってきますね。

手動採番の場合は、もちろん MAX + 1 でも良いと思います。
ただし、複数の接続からほぼ同時に処理がおこなれた場合に、
値の重複が発生しないような設計にしておいてください。

たとえば 1〜5 が登録済みで、A と B からほぼ同時に採番される場合、
  (1) A が MAX+1 を取得  →  6 番をGET
  (3) A がレコード追加  →  6 番を登録
  (2) B が MAX+1 を取得  →  7 番をGET
  (4) A がレコード追加  →  7 番を登録
となれば良いですが、ごく僅かなタイミングの差で、
  (1) A が MAX+1 を取得  →  6 番をGET
  (2) B が MAX+1 を取得  →  6 番をGET
  (3) A がレコード追加  →  6 番を登録
  (4) A がレコード追加  →  重複エラー
となってはいけませんよね。


また、DB 側で自動採番されるタイプの列(Jet のオートナンバー等)の場合は、
DataColumn を AutoIncrement にしておく方法を使う事もできます。
http://msdn.microsoft.com/library/ja/cpguide/html/cpconupdatingdatabasewithdataadapterdataset.asp

たとえば、DataSet 側では、-1,-2,-3,…という負数で採番しておき、
TableAdapter(あるいはDataAdapter)の InsertCommand では、その列の値を
利用させず、データベース側の自動採番に任せるという手法です。

多くの場合、オートナンバー列は 1,2,3,…という正数で管理される事が多いため、
DataTable側では一時的に、(登録までの間は)マイナス値を使っておくことで、
重複を避けるという常套手段です。


これらは、どちらの方法が良い/悪いというものでも無いので、
Franz さんのシステムに合わせて、都合のよい方法を選んでみてください。

編集 削除
Franz  2008-04-11 21:37:42  No: 144611  IP: 192.*.*.*

魔界の仮面弁士さんありがとうございます。
採番方法よくわかりました。
自分の方法が悪くなく安心しました。値の重複の件、考えます。
皆様、本当にありがとうございました。

編集 削除