私が取り組んでいる関連テクノロジーは次のとおりです。
- DevartのドットコネクトforOracle(Linq-to-Sql for Oracleを容易にするため)。
- 強く型付けされたADO.NETデータセット。
- Oracleデータベース。
課題は次のとおりです。
- 私のレガシーコードは、ADO.NETデータセットとテーブルアダプターを使用してデータベースの更新を送信します。
- そのコードをLinq-to-Sqlに変換し始めたいのですが、コードのチャーンとリスクを最小限に抑えるために少しずつ変換したいと思います。
これが私の概念実証スキーマです。
親テーブル
- Parent.Id
- 親の名前
子テーブル
- Child.Id
- Child.ParentId
- Child.Name
これが私の概念実証コードブロックです:
using System;
using System.Data.Common;
using DevArtTry1.DataSet1TableAdapters;
namespace DevArtTry1
{
class Program
{
static void Main(string[] args)
{
using (DataContext1 dc = new DataContext1())
{
dc.Connection.Open();
using (DbTransaction transaction = dc.Connection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
{
dc.Transaction = transaction;
Parent parent = new Parent();
parent.Id = 1;
parent.Name = "Parent 1";
dc.Parents.InsertOnSubmit(parent);
dc.SubmitChanges(); // By virtue of the Parent.Id -> Child.ParentId (M:N) foreign key, this statement will impose a write lock on the child table.
DataSet1.CHILDDataTable dt = new DataSet1.CHILDDataTable();
DataSet1.CHILDRow row = dt.NewCHILDRow();
row.ID = 1;
row.PARENTID = 1;
row.NAME = "Child 1";
dt.AddCHILDRow(row);
CHILDTableAdapter cta = new CHILDTableAdapter();
// cta.Transaction = transaction; Not allowed because you can't convert source type 'System.Data.Common.DbTransaction to target type 'System.Data.OracleClient.OracleTransaction.
cta.Update(dt); // The thread will encounter a deadlock here, waiting for a write lock on the Child table.
transaction.Commit();
}
}
Console.WriteLine("Successfully inserted parent and child rows.");
Console.ReadLine();
}
}
}
- 上記のコメントが示すように、スレッドは子テーブルの書き込みロックを無期限に待機するため、子データアダプターの更新呼び出しで無期限に停止します。[外部キーの関係に注意してください:Parent.Id-> Child.ParentId(M:N)]
これが私の質問です:
- コードブロック全体をトランザクションでラップしたいと思います。
- これはできますか?それを考慮して:
- Linq-to-SqlのSubmitChangesメソッドを使用して親テーブルの更新をコミットしたい...
- そして、ADO.NETデータセットテーブルアダプターを使用して、子テーブルの更新をコミットしたいと思います。
ここに2つの興味深い脚注があります:
- このすべてが逆に機能します。つまり、データアダプターを使用して親テーブルに変更を送信し、linq-to-sqlを使用して子テーブルに変更を送信する場合は、機能します。
トランザクションをデータアダプターに明示的にアタッチしようとしましたが、トランザクションのタイプが異なるため、コンパイラーはそれを許可しません。
CHILDTableAdapter cta = new CHILDTableAdapter(); cta.Transaction = transaction; // Not allowed because you can't convert source type 'System.Data.Common.DbTransaction' to target type 'System.Data.OracleClient.OracleTransaction'. cta.Update(dt); transaction.Commit();