- PR -

identityな列への登録と値取得を1命令で行う方法

1
投稿者投稿内容
どてかぼちゃ
会議室デビュー日: 2005/09/12
投稿数: 5
投稿日時: 2005-09-19 00:07
ASP.Net初めて半月のPGです。

Webであるシステムのユーザーを管理するようなプログラムを作成しているのですが、
壁にぶつかっているので質問します。
処理としては以下の様なことを行おうと思っています。

1.利用者がフォームにデータを入力
2.該当ユーザのデータが存在しなければDBに新規登録
3.登録したデータのキー値を元にWebサーバにディレクトリを作成する。

ここで、DataAdapterを利用してidentityなキーを持つテーブルにデータを登録している
のですが、DataAdapterがデータを更新したタイミングで新たに追加された値をとる
方法がわからず困っています。

データ登録後、改めて@@IDENTITYやSCOPE_IDENTITYや、キーの最大値を求めるSQLを
投げるという手も有りますが、登録→取得とアプリ側で処理を分けるとアプリ側で
排他制御をする必要があるため、信頼性が下がるのでこの方法はできれば遠慮したい
ところです。

ADOのようにUpdateと同時に値を取得する方法をご存知の方はいらっしゃいませんで
しょうか?

以下は現在「とりあえず動いている」ソースです。
----------------------------------------------------

  strKey = Session("UserNo")
  strSQL = "select * from M_User where UserID = @ID"

  Dim con As New SqlConnection(ConfigurationSettings.AppSettings.Get("g_ConStr"))
  con.Open()
  Dim cmd As New SqlCommand(strSQL, con)
  Dim da As New SqlDataAdapter()

  '☆ UserIDからユーザーを引っ張る
  Dim param As SqlParameter
  Dim ds As New DataSet()

  param = cmd.CreateParameter()
  param.ParameterName = "@ID"
  param.Value = strKey
  cmd.Parameters.Add(param)

  da.SelectCommand = cmd
  da.Fill(ds, "M_User")

  Dim dt As DataTable = ds.Tables("M_User")
  Dim dr As DataRow

  If dt.Rows.Count > 0 Then
    '該当データ発見!
    dr = dt.Rows(0)
    flgNew = False
  Else
    '☆ データが無いときは追加する。
    dr = dt.NewRow()
    flgNew = True
  End If

〜〜〜以下、drにデータ設定〜〜〜



〜〜〜設定終了〜〜〜

  If flgNew Then
    '☆ 新規追加の場合は行を追加する。
    dt.Rows.Add(dr)
  End If

  Try
    Dim ret As Integer
    ret = da.Update(ds.Tables("M_User"))
    '☆本来ならこのUpdateを行った時点で登録したデータに入るIDがほしい。

    If ret <> 1 Then
      '☆ 失敗!
      Exit Function
    End If
  Catch ex As SqlClient.SqlException
    Update = False
    Exit Function
  End Try
  Dim drs() As DataRow

  '☆ 登録した情報を元にデータを検索。
  drs = ds.Tables("M_User").Select("UserID=" & Session("UserNo"))

  '☆IDENTITYな値取得!
  iPlanID = drs(0)("PlanID")

〜〜〜以下、ディレクトリを操作するコードが続く〜〜

DataRowの内容を取得元と同期するメソッドがあれば簡単に解決するのですが…


[ メッセージ編集済み 編集者: どてかぼちゃ 編集日時 2005-09-20 11:25 ]
どてかぼちゃ
会議室デビュー日: 2005/09/12
投稿数: 5
投稿日時: 2005-09-20 13:41
Updateと同時に取得はできないようなので@@identityの値を取得するようにしました。

@@identityは同一コネクション中で最後にinsertしたidentityな値を保持している
らしいので排他制御を行わなくても自分がinsertを行ったレコードのidentityな項
目の値を保持している様でした。

ループで一気に複数件登録する場合など、Update毎にSelectを投げるのは
処理効率が悪そうですが…

//ADOにできるのにADO.Netでできないというのは何か納得いかない物がありますが…

[ メッセージ編集済み 編集者: どてかぼちゃ 編集日時 2005-09-20 13:55 ]
todo
ぬし
会議室デビュー日: 2003/07/23
投稿数: 682
投稿日時: 2005-09-20 14:18
引用:

DataRowの内容を取得元と同期するメソッドがあれば簡単に解決するのですが…



試していないけど..

da.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord;
da.InsertCommand.CommandText = "INSERT INTO テーブル名 (列名) VALUES (値); SELECT * FROM テーブル名 WHERE (連番 = SCOPE_IDENTITY())";

参考
http://www.microsoft.com/japan/msdn/library/ja/cpref/html/frlrfSystemDataCommonDataAdapterClassUpdateTopic.asp
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=21176&forum=7
どてかぼちゃ
会議室デビュー日: 2005/09/12
投稿数: 5
投稿日時: 2005-09-20 16:21
todo様

ご意見ありがとうございます。
実はSqlCommandBuilderを利用し、データセットから自動的にコマンドを生成
しているため、この方法は利用できませんでした。

Update前にコマンドビルダからInsertCommandのオブジェクトを取得し、
CommandTextプロパティに、Select句を追加してみたのですが、Updateの時点で
SqlCommandBuilderが自動的にDataAdapterのCommandを更新してしまい、IDは
取得できませんでした。

残念ながら今回はもう一度クエリを投げて@@identityを取得しようと思います。
todo
ぬし
会議室デビュー日: 2003/07/23
投稿数: 682
投稿日時: 2005-09-20 16:55
http://dotnet247.com/247reference/msgs/12/61091.aspx
どてかぼちゃ
会議室デビュー日: 2005/09/12
投稿数: 5
投稿日時: 2005-09-20 17:42
todo様
私が躓いていた部分と全く同じ場所ですね。
的確なアドバイスありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)