以下是我正在使用的相关技术:
- Devart 的 dot Connect for Oracle(为 Oracle 提供方便的 Linq-to-Sql)。
- 强类型 ADO.NET 数据集。
- 一个甲骨文数据库。
这是挑战:
- 我的旧代码使用 ADO.NET 数据集和表适配器提交数据库更新。
- 我想开始将该代码转换为 Linq-to-Sql,但我想零敲碎打地做,以尽量减少代码流失和风险。
这是我的概念验证模式:
父表
- 父代号
- 父母名字
子表
- 孩子.Id
- Child.ParentId
- 子名
这是我的概念验证代码块:
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 数据集表适配器对 Child 表进行更新。
这里有两个有趣的脚注:
- 这整个事情是相反的。也就是说,如果我想使用数据适配器提交对父表的更改并使用 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();