2009-05-20 63 views
0

下面是我的工作相關的技術:您可以在單個事務中包含linq-to-sql更改和ADO.NET數據集表適配器更新嗎?

  • Devart的點連接的Oracle(方便的LINQ到SQL爲Oracle)。
  • 強類型的ADO.NET數據集。
  • Oracle數據庫。

這裏的挑戰:

  • 我的舊代碼提交與ADO.NET數據集和表適配器的數據庫更新。
  • 我想開始將該代碼轉換爲Linq-to-Sql,但我想盡量減少代碼流失和風險。

這裏是我的理念架構的證明:

父表

  • Parent.Id
  • Parent.Name

子表

  • 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(); 
     } 
    } 
} 

  • 正如上述評論表明,線程將無限期停止在子數據適配器的更新調用上因爲它將無限期地等待Child表上的寫入鎖定。 [注的外鍵關係:Parent.Id - > Child.ParentId(M:N)]

我的問題是:

  • 我想包裝整個代碼塊 在一個事務中。
  • 我可以這樣做嗎?考慮到:
    • 我要提交對母表的更新與 的LINQ到SQL的的SubmitChanges方法 ...
    • 我想在子表上提交的 更新與 ADO.NET數據集表格適配器

這裏有兩個有趣的註腳:

  1. 這整個事情在 反向工程。也就是說,如果我想 用數據適配器提交對父表 的更改並將其更改爲 子表與linq-to-sql ... 即將工作
  2. 我試圖顯式附加事務到dataadapter,但編譯器不會允許它,因爲它是一種不同類型的事務。

       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(); 
    

回答

1

我不知道甲骨文的交易什麼...但在DOTNET方面,你應該罰款,以控制自己的交易。確保兩種技術都使用相同的連接實例。

當我們通過連接,而不是通過ORM控制事務,我們使用的交易範圍:http://msdn.microsoft.com/en-us/library/ms172152.aspx

0

使用TransactionScope類。

請注意,如果您使用不同的數據庫(或它們駐留在不同的服務器上),則需要檢查DTC配置。

1

我有同樣的問題,遇到這兩種錯誤:

  • 完整性約束衝突(ORA-02291)
  • 「不能使用相同的密鑰插入實體如果key不是數據庫生成」

問題在於子對象的標識列未正確設置。如果DotConnect LINQ不假設身份密鑰,則對象屬性似乎設置爲臨時的,導致非順序更新,從而導致完整性違規。

這裏的修復:

  • LINQ需要知道孩子的主鍵是實體按鍵,並自動生成。
  • 在Oracle中,爲子對象設置一個自動遞增的鍵。
  • 首先創建一個序列:

    DROP SEQUENCE MyChild_SEQ; 
        CREATE SEQUENCE MyChild_SEQ 
         MINVALUE 1 
         MAXVALUE 999999999999999999999999999 
         START WITH 1 
         INCREMENT BY 1 
         CACHE 20; 
    
  • 下一頁創建OnInsert觸發:

    CREATE OR REPLACE TRIGGER MyChild_AUTOINC 
    BEFORE INSERT 
    ON MyChildObject 
    FOR EACH ROW 
    BEGIN 
        SELECT MyChild_SEQ.nextval 
        INTO :NEW.MyChild_ID 
        FROM dual; 
    END MyChild_AUTOINC ; 
    ALTER TRIGGER MyChild_AUTOINC ENABLE 
    
  • 修改存儲模型以納入自動生成新主鍵:

    • 在dotConnect的EntityDeveloper中,打開您的LINQ存儲模型(.LQML文件)。
    • 將子對象的實體鍵設置爲「自動生成的值」,並自動同步到「OnInsert」。
    • 保存存儲模型,並在Visual Studio中清理並重建解決方案。
    • 刪除任何明確設置子主鍵的代碼。
      • LINQ將隱式識別爲自動遞增,並檢索觸發器創建的ID。
  • 在代碼,創建子對象後,將其連接到父,如下:

    ChildType newChild = new ChildType(); 
    DataContext.InsertOnSubmit(newChild); 
    Parent.Child = newChild; 
    

這裏有更多的資源:

乾杯!

相關問題