【问题标题】:Inserting data into different tables at the same time with Linq-to-SQL使用 Linq-to-SQL 将数据同时插入到不同的表中
【发布时间】:2012-03-02 16:35:59
【问题描述】:

我在这里有 Linq-to-SQL 代码,它将数据提交到各自表中的数据库中, PatientInformationResponsibleParty:

public void addPatientInformation() { 
   using(DbClassesDataContext myDb = new DbClassesDataContext(dbPath)){
      PatientInfo patientInfo = new PatientInfo();

      patientInfo.Phy_ID = physcianID;
      patientInfo.Pat_First_Name = txtFirstName.Text;
      patientInfo.Pat_Middle_Name = txtMiddleName.Text;
      patientInfo.Pat_Last_Name = txtLastName.Text;
      patientInfo.Pat_Gender = cmbGender.Text;
      patientInfo.Pat_Marital_Status = cmbMaritalStatus.Text;
      patientInfo.Pat_Date_Of_Birth = dtpDOB.Value;
      patientInfo.Pat_Home_Add = txtHomeAdd.Text;
      patientInfo.Pat_Home_Num = txtPhone.Text;
      patientInfo.Pat_Work_Add = txtWorkAdd.Text;
      patientInfo.Pat_Work_Num = txtWorkPhone.Text;
      patientInfo.Pat_Prim_Physician = txtPrimPhysician.Text;
      patientInfo.Pat_Ref_Physician = txtRefePhysician.Text;

      myDb.PatientInfos.InsertOnSubmit(patientInfo);
      myDb.SubmitChanges();
   }
}

public void addResponsiblePartyInformation() { 
   using(DbClassesDataContext myDb = new DbClassesDataContext(dbPath)){
      ResponsibleParty responsibleParty = new ResponsibleParty();

      responsibleParty.Res_First_Name = txtResFirstName.Text;
      responsibleParty.Res_Middle_Init = txtResMiddleName.Text;
      responsibleParty.Res_Last_Name = txtResLName.Text;
      responsibleParty.Res_Gender = cmbResGender.Text;
      responsibleParty.Res_Marital_Status = cmbResMaritalStatus.Text;
      responsibleParty.Res_Date_Of_Birth = dtpResDOB.Value;
      responsibleParty.Res_Home_Add = txtResHomeAdd.Text;
      responsibleParty.Res_Home_Num = txtResPhone.Text;
      responsibleParty.Res_Work_Add = txtResWorkAdd.Text;
      responsibleParty.Res_Work_Num = txtResWorkPhone.Text;

      myDb.ResponsibleParties.InsertOnSubmit(responsibleParty);
      myDb.SubmitChanges();
   }

还有一个名为

的方法
public void submitInformationToDatabase() {
            addPatientInformation();
            addResponsiblePartyInformation();
            MessageBox.Show("Patient Demographics Has Been added.");
        }

有什么方法可以一次提交吗?

【问题讨论】:

    标签: c# .net sql linq linq-to-sql


    【解决方案1】:

    两种选择:

    • 传入数据上下文,不要每次都调用SubmitChanges()(也许让它可选)
    • 使用事务

    对于第二个,TransactionScope 可以用于执行此操作,而无需更改这两种方法:

    using(var tran = new TransactionScope()) {
        method1(...);
        method2(...);
        tran.Complete();
    }
    

    或者使用其他方法(添加可选参数后):

    using(var ctx = new SomeDataContext(...)) {
        method1(ctx, ..., submitChanges: false);
        method2(ctx, ..., submitChanges: false);
        ctx.SubmitChanges();
    }
    

    【讨论】:

    • 这看起来很有趣,但到目前为止我不知道什么是交易范围。
    • @user962206 这是一个“环境事务”,可供多个提供商使用。对于 SQL Server,它同时支持 LTM 和 DTC(“轻量级事务管理器”和“分布式事务协调器”)机制。或者用英语:您将获得围绕该批次的数据库事务,因此它使用通常的“ACID”规则提交。
    • 你能提供例子吗? ??我没有得到方法(cyx,...,submitChanges:false);有什么更简单的吗?
    • @user 如图所示,“更简单”是事务范围。我的意思是,其他设置是:与其在这些方法中创建数据上下文,不如在外部创建数据上下文并将其作为参数传递,然后在外部调用 SubmitChanges
    【解决方案2】:

    如果您可以将代码重构为类似于以下示例的内容,则两条记录将插入同一个 submit

    using(DbClassesDataContext myDb = new DbClassesDataContext(dbPath)){
    
          myDb.PatientInfos.InsertOnSubmit(patientInfo);
          myDb.ResponsibleParties.InsertOnSubmit(responsibleParty);
          myDb.SubmitChanges();
    }
    

    【讨论】:

      【解决方案3】:

      将连接作为参数传递给这两种方法并使用 System.Transaction:

      public void submitInformationToDatabase() {
               using (System.Transactions.TransactionScope tr = new System.Transactions.TransactionScope())
                 {
                  System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(dbPath);
                  con.Open();
                  addPatientInformation(con);
                  addResponsiblePartyInformation(con);
                  tr.Complete();
                 }
                  MessageBox.Show("Patient Demographics Has Been added.");
              }
      

      【讨论】:

      • 您似乎建议使用连接级事务,但您说明的是环境事务(TransactionScope)。如果使用环境事务,则无需对现有方法进行任何更改;在这种情况下,您不需要传递连接。也就是说,它有助于使其更有可能使用 LTM 而不是 DTC - 这就是您想要表达的意图吗?
      • 由于两个数据上下文使用相同的连接字符串,因此无需打开 2 个连接并加载更多池,以及一个连接的一个“全局”事务
      • 那不会发生;这里的数据上下文范围很窄,并且会干净地处理(释放回池)。实际上,它变得更加有趣,因为数据上下文也可以(取决于它的设置方式)在不需要时释放连接 - iirc 这是传入连接字符串时的默认设置。这并不意味着它每次都有不同的底层连接。
      • 感谢您的信息,但无论如何有时我们需要设置Pooling=false,因为经过一个小时的艰苦测试,它已满
      • 如果您必须关闭池化,您可能会出错(可能无法可靠地释放它们?)。如果你真的需要一个更大的池,你可以增加它。我们在 stackoverflow 使用标准池化。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-03
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多