在三层架构中,BLL层一般会用到事务,那在业务层中就必须用到Connection对象,去创建事务,我的理解对吗?
大家平时都是怎么用的,能说说吗?
谢了!

解决方案 »

  1.   

    业务层中就必须用到Connection对象?????先吃饭!!
      

  2.   

    数据库事务不是用sqlConnection创建的吗?
      

  3.   

    BLL层调用DAL层方法,在数据操作层使用事务
    SQL一般写在DAL层,通过数据库类实现调用。 
    在BLL通过接口调用DAL方法 
    Model,实现业务实体。 
    IDAL,实现接口。 
    SQLServerDAL,实现接口里的方法。 
    web.config里的配置信息,为SQLServerDAL的程序集。 
    DALFactory,返回程序集的指定类的实例。 
    BLL,调用DALFactory,得到程序集指定类的实例,完成数据操作方法。 
    WEB,调用BLL里的数据操作方法。 
    看看petshop
    http://topic.csdn.net/u/20090912/17/e9b2dd15-f29b-495f-855c-187ff1807511.html?90127
      

  4.   

    在sqlHelper里面处理事务,这里的事务是传进来的参数。也就是说在调用的时候,需要在BLL里面声明一个事务,然后当作参数传给DAL的方法,DAL调用SqlHelper。
    我是这么认为的,其实我还没用过事务。不知道对不对,仅供参考~
      

  5.   

    C#中的事务处理
    http://hi.baidu.com/%E8%AA%BC%C7%D3%DA%D0%C4/blog/item/f470181caa62678e86d6b66a.html
      

  6.   


    SqlConnection myConnection = new SqlConnection("Data Source=localhost;Initial Catalog=Northwind;Integrated Security=SSPI;");
    myConnection.Open();SqlTransaction myTrans = myConnection.BeginTransaction(); //使用New新生成一个事务
    SqlCommand myCommand = new SqlCommand();
    myCommand.Transaction = myTrans;try
    {
    myCommand.CommandText = "Update Address set location='23 rain street' where userid='0001'";
    myCommand.ExecuteNonQuery();
    myTrans.Commit();
    Console.WriteLine("Record is udated.");
    }
    catch(Exception e)
    {
    myTrans.Rollback();
    Console.WriteLine(e.ToString());
    Console.WriteLine("Sorry, Record can not be updated.");
    }
    finally
    {
    myConnection.Close();
      

  7.   

    处理事务一般都在SQLHelper类中封装好了把SqlTrancation参数传进去   在BLL层直接调用 
      

  8.   

    BLL层是什么层  三层架构 我只知道  MVC 啊!!!
      

  9.   

    在BLL层调用时需要SqlTrancation,也就是说在BLL层还得用SqlConnection对象的BeginTrancation来得到这个参数,但是总感觉在BLL有个SqlConnection怪怪的!
    再没有别的办法了吗?
      

  10.   

    在三层架构中,BLL层一般会用到事务,那在业务层中就必须用到Connection对象,去创建事务,我的理解对吗? 
    ----------------
    业务层中当然可以不用connection.可以在dal中声明一个属性来包装DbTransaction,
    然后bll中可以得到.
    对于要用事务的方法传同一个DbTransaction即可.
    还可以参考TransactionScope这个类..
      

  11.   

    处理事务一般都在SQLHelper类中封装好了把SqlTrancation参数传进去  在BLL层直接调用
      

  12.   

    LZ的意思我理解是你在逻辑层需要进行事务处理。比如某个业务在某些情况下要回滚处理。一种做法是在必要的地方用SQL的raiseerror方法行进抛出。还有就是sqlhelper的事务控制,将脚本按逻辑分开,必要是进行回滚。第二种方法应该比较好。如果你在业务层里写connection,那就不是三层了。还有小项目完全没必要三层。面向过程,把代码结构写写清楚,逻辑分分开就足够了。
      

  13.   


    不使用connection对象。正如#19楼所说,传递或者说保持一个IDbConnection类型的对象即可。
      

  14.   

    在DAL内部,才自动根据IDbConnection的ConnectionString 属性来创建局部的Connection,而根本不需要共享什么Connection。
      

  15.   

    即使是在简单的程序中,也并不是“就必须用到Connection对象”的。实际上,仅仅共享ConnectionString字符串,而Connection对象则是“临时创建、及时释放”的。如果以为只有共享对象才能“提高性能”,不但根本不知道.net的连接池机制,而且还经常会造成程序运行时崩溃。
      

  16.   

    public void doAdd(Model.FriendGroupInfo friendGroup)
            {
                SqlParameter[] friendGroupParams = GetFriendGroupAddParameters();
                SetFriendGroupAddParameters(friendGroupParams, friendGroup);            using (SqlConnection conn = new SqlConnection(SQLHelper.CONN_STRING_NON_DTC))
                {
                    conn.Open();
                    using (SqlTransaction trans = conn.BeginTransaction())
                    {
                        try
                        {
                            SQLHelper.ExecuteNonQuery(trans, CommandType.Text, SQL_INSERT_FRIENDGROUP, friendGroupParams);
                            trans.Commit();
                        }
                        catch(SqlException err)
                        {
                            trans.Rollback();
                            throw err;
                        }
                    }
                }
            }
    sqldal层事务用法
      

  17.   

    楼主所说的事务是真实的应用,事务是跨很多DAL方法的,而且这些DAL方法互相之间可以根本没有直接联系,而完全是BLL把他们联系在一起(调用)的。而不是楼上的 doAdd 这种在一个DAL方法内部使用事务。
      

  18.   

    doAdd 在“楼上的楼上”,呵呵。
      

  19.   


    满拧!使用SqlTransaction 的Connection属性得到SqlConnection,或者(真正可靠的做法是)使用ConnectionString来创建SqlConnection并且将SqlTransaction 的实例对象设置到随后的SqlCommand对象的Transaction属性上。其实SqlConnection跟SqlConnection可以没有任何关系。
      

  20.   

    楼主知道三层就应该知道操作数据库的操作在DAL层中(比如SQLServerDAL),在DAL层中使用事务很简单,我直接贴个代码。#region 修改订单状态
            public bool UpdateOrderState(string orderID, Model.T_OrderState orderState)
            {
                bool result = false;
                using (SqlConnection conn = new SqlConnection(Config.SQLServerConnStr))
                {
                    conn.Open();
                    string transName = "UpdateOrderState";
                    SqlTransaction trans = conn.BeginTransaction(transName);
                    try
                    {
                        #region 更新订单状态
                        SqlParameter[] parmsUpdateOrderState ={
                            new SqlParameter("@OrderID",orderID),
                            new SqlParameter("@OrderState",orderState.OrderState),
                            new SqlParameter("@UpdateStateDate",DateTime.Parse(DateTime.Now.ToString()))
                        };                    if (orderState.OrderState.Equals(Helper.OrderState.HasPayed))
                            SqlHelper.ExecuteNonQuery(trans, CommandType.StoredProcedure, StoredProcedureName.sp_UpdateOrderStatePayAll.ToString(), parmsUpdateOrderState);
                        else
                            SqlHelper.ExecuteNonQuery(trans, CommandType.StoredProcedure, StoredProcedureName.sp_UpdateOrderState.ToString(), parmsUpdateOrderState);                    #endregion                    #region 写入订单状态登记
                        SqlParameter[] parmsInsertOrderState ={
                            new SqlParameter("@OrderID",orderID),
                            new SqlParameter("@OrderState",orderState.OrderState),
                            new SqlParameter("@AddedDate",DateTime.Parse(DateTime.Now.ToString())),
                            new SqlParameter("@AdminName",orderState.AdminName),
                            new SqlParameter("@OldOrderState",orderState.OldOrderState),
                            new SqlParameter("@Re",orderState.Re),
                            new SqlParameter("@OperationType",orderState.OperationType)
                        };                    SqlHelper.ExecuteNonQuery(trans, CommandType.StoredProcedure, StoredProcedureName.sp_InsertOrderState.ToString(), parmsInsertOrderState);
                        #endregion                    trans.Commit();
                        result = true;
                    }
                    catch (Exception ex)
                    {
                        string tempex = ex.ToString();
                        trans.Rollback(transName);
                        result = false;
                    }
                }            return result;
            }
            #endregion
    关于三层,3楼的老大已经说的很明白了,代码的话可以参考:普通三层结构示例项目源码 和 工厂模式三层结构示例项目源码,看着例子自己动手写个小demo,很简单,自己实践一下就可以搞定了。
      

  21.   

    自动事务处理是 COM+ 提供的一个服务,用于在设计时配置类,以便在运行时参与事务。要使用此服务,该类必须直接或间接从 System.EnterpriseServices.ServicedComponent 类派生。COM+ 使您能够为要求事务的每一个类指定不同的事务超时。可以使用这一功能解决冲突的超时情况,如强制短时间事务和允许长时间运行的批存储过程。如果不指定事务超时值,则使用计算机的整个系统范围的超时值。事务超时是以秒为单位度量的整数值。有关如何设置事务超时的示例,请参见如何:设置事务超时。请参见
    任务
    如何:在 .NET Framework 类中使用自动事务
    如何:使用 SetAbort 和 SetComplete 方法
    如何:对事务识别类设置 AutoComplete 属性
    如何:设置事务超时
    如何:创建使用自动事务的 Web 服务方法参考
    System.EnterpriseServices 命名空间概念
    自动事务和 .NET Framework 类
    自动事务中的投票
    自动事务和 ASP.NET
    自动事务和 XML Web 服务
    可用的 COM+ 服务摘要
      

  22.   

    下面的过程介绍如何准备类以参与自动事务。准备类以参与自动事务
    从 ServicedComponent 类派生您的类,然后将 TransactionAttribute 应用于该类。下例显示如何将 TransactionAttribute 属性应用到从 ServicedComponent 类派生的类。Visual Basic  复制代码 
    <Transaction(TransactionOption.Required)> Public Class Account
       Inherits ServicedComponent
       '. . .
    End Class
     
    C#  复制代码 
    [Transaction(TransactionOption.Required)]
    public class Account : ServicedComponent
    {
      //. . .
    }
     对于不存在异常时必须为其自动调用 ContextUtil.SetComplete 方法的每个方法,应用 AutoComplete 属性。下面的示例显示如何应用 AutoComplete 属性。Visual Basic  复制代码 
    <AutoComplete()> Public Sub Debit(amount As Integer)
          ' Do some database work. Any exception thrown here aborts the 
          ' transaction; otherwise, transaction commits.
    End Sub
     
    C#  复制代码 
    [AutoComplete]
    public void Debit(int amount)
    {
        // Do some database work. Any exception thrown here aborts the 
        // transaction; otherwise, transaction commits.
    }
     用强名称为程序集签名。要使用属性为程序集签名,请使用 Sn.exe 创建一个密钥对,然后添加 AssemblyKeyFileAttribute 或 AssemblyKeyNameAttribute 程序集属性并指定包含该密钥对的文件的名称,以使用强名称为该程序集签名。Visual Basic  复制代码 
    <assembly: AssemblyKeyFileAttribute("TestApp.snk")>
     
    C#  复制代码 
    [assembly: AssemblyKeyFileAttribute("TestApp.snk")]
     向 COM+ 目录注册包含此类的程序集。如果类的客户端调用实例是由公共语言运行库管理的,则注册将自动执行。但是,如果预期非托管调用方可能创建和调用类的实例,请使用 .NET 服务安装工具 (Regsvcs.exe) 手动执行注册。示例
    Visual Basic  复制代码 
    ' -----------------------------------------------------------------
    ' TestApp.vb
    ' Generate a Strong name: 
    '    sn -k TestApp.snk
    ' Compile the code:
    '    vbc /target:exe /r:System.EnterpriseServices.dll TestApp.vb
    ' Run TestApp:
    '    start TestApp.exe
    ' -----------------------------------------------------------------
    Option Explicit
    Option StrictImports System
    Imports System.Runtime.CompilerServices
    Imports System.EnterpriseServices
    Imports System.Reflection'Registration details.
    'COM+ application name as it appears in the COM+ catalog.
    <assembly: ApplicationName("TestApp")>
    'Strong name for assembly.
    <assembly: AssemblyKeyFileAttribute("TestApp.snk")><Transaction(TransactionOption.Required)> Public Class Account
       Inherits ServicedComponent
       
       'Provides SetComplete behavior in the absence of exceptions.
       <AutoComplete()> Public Sub Debit(amount As Integer)
          ' Do some database work. Any exception thrown here aborts the 
          ' transaction; otherwise, transaction commits.
       End Sub
    End ClassPublic Class client
       Public Shared Sub Main()
          Dim accountX As New Account()
          accountX.Debit(100)
          Environment.Exit(0)
       End Sub
    End Class 
    C#  复制代码 
    // -----------------------------------------------------------------
    // TestApp.cs
    // Generate a Strong name: 
    //    sn -k TestApp.snk
    // Compile the code:
    //    csc /target:exe /r:System.EnterpriseServices.dll TestApp.cs
    // Run TestApp:
    //    start TestApp.exe
    // -----------------------------------------------------------------
    using System;
    using System.Runtime.CompilerServices;
    using System.EnterpriseServices;
    using System.Reflection;//Registration details.
    //COM+ application name as it appears in the COM+ catalog.
    [assembly: ApplicationName("TestApp")]
    //Strong name for assembly.
    [assembly: AssemblyKeyFileAttribute("TestApp.snk")][Transaction(TransactionOption.Required)]
    public class Account : ServicedComponent
    {
      //Provides SetComplete behavior in the absence of exceptions.
      [AutoComplete]
      public void Debit(int amount)
      {
         // Do some database work. Any exception thrown here aborts the 
         // transaction; otherwise, transaction commits.
      }
    }public class client
    {
      public static int Main() 
      {
        Account accountX = new Account();
        accountX.Debit(100);
        return 0;
      }
    } 请参见
    概念
    自动事务中的投票其他资源
      

  23.   

    此示例显示如何使用 System.EnterpriseServices.ContextUtil 类的静态 SetComplete 和 SetAbort 方法。有关这些方法的更多信息,请参见自动事务中的投票。示例
    Visual Basic  复制代码 
    'Try to do something crucial to the transaction in progress.
    If Not DoSomeWork() Then
       ContextUtil.SetAbort()   'Something goes wrong.
    Else
       ContextUtil.SetComplete()   'All goes well.
    End If
     
    C#  复制代码 
    //Try to do something crucial to the transaction in progress.
    if( !DoSomeWork() )
    {
       ContextUtil.SetAbort();   //Something goes wrong.
    }
    else
    {
       ContextUtil.SetComplete();   //All goes well.
    }
     编译代码
    此示例要求:对 System 和 System.EnterpriseServices 命名空间的引用。请参见
    概念
    自动事务中的投票
      

  24.   

    信楼上的吧,COM+,容器自动管理,完全不用关心,异常舒服。
    在JAVA里面他妈的更爽了,写几个源注释啥都不管,事务都没人讨论了
      

  25.   

    不要老拿PetShop说事,行不???
      

  26.   

    MS提供的有DAL实现类  希望看一下 里面有对事务的操作
      

  27.   

    其实楼主这个问题 以前我翻过很多帖子 也在 网上找过
    很郁闷 都没找到一个好的解决方案问题可以缩成:如何在业务逻辑层里使用事务事务的处理 放在数据库里实现 当然是最好的
    但是在DAL层里使用事务的话 似乎让各个数据访问类直接的耦合性又增加了  数据访问层的作用应该只是
    简单的 增 删 改 查 等基本操作
    按设计的原则  事务放在业务逻辑层 处理应该是最好的  希望大神们 给出一个好的解决方案 支持楼主继续把此贴顶下去
      

  28.   

        确实有些迷茫!不过19楼lovehongyun和sp1234给了我很大启示!
        不加事务的传连接字符串或连接对象,都是临时创建,然后释放!
        加事务的可以在DBHelper中封装一个SqlTransaction属性,里面可以用一个静态的连接,反正只要保证在同一个事务中SqlTransation唯一就行!然后再BLL层直接调用这个SqlTransation即可!
         不知道我说的对不?
      

  29.   


    这位说的很清楚了只要保持DbTransaction 一个引用就可以再不同的DAL传递
    最终回滚也是整个范围内的回滚了
      

  30.   


    SP老大,有没相关的BLL 调用不同DAL 集合,加事物的参考代码呢
    谢谢啦
      

  31.   


    //test.cs
    public bool Savexx(ZfJbXx zfjbxx,string cymj)
      {
       sql1="INSERT INTO tablename(Id,col1,col2) VALUES(@Id,@col1,@col2)   update tablename2 set col=@col";
       sql2="INSERT INTO tablename3(Id,col1,col2) VALUES(@Id,@col1,@col2)";   //参数设置(略)   using(SqlTransaction tran = SqlHelper.BeginTransaction(SqlHelper.DBConnectionString))
       {
        try
        {     
         //SqlHelper.TransExecuteNonQuery(tran,CommandType.Text,sql1,parms);
       
         SqlHelper.ExecuteNonQuery(tran,CommandType.Text,sql1,parms);//执行多个不同的DAL
         SqlHelper.ExecuteNonQuery(tran,CommandType.Text,sql2,parms);//执行多个不同的DAL     tran.Commit();
         
         return true;
        }
        catch
        {
         tran.Rollback();
         return false;
        }
       }
    上面就可以实现你说的,封装下
      

  32.   

    看看nh就知道了
    在bll BeginTransaction(),这个事物为一个请求内共享(bs)或者一个线程内共享(cs),然后多个dal就可以使用了
      

  33.   


    不是太明白,这个代码是那一层的?BLL里面不是调用DAL,而在dal中调用SqlHelper.ExecuteNonQuery吗?我也想看看BLL调用DAL中不同类中方法时使用事务的例子。
      

  34.   

    他这个只是举个例子而已,是个业务!就是在业务层的方法中,如下:
    using(SqlTransaction tran= SqlHelper.BeginTransaction(SqlHelper.DBConnectionString))
        {try
         {
          //多个DAL层带事务的方法!
          tran.Commit();
          returntrue;
         }catch
         {
          tran.Rollback();returnfalse;
         }
    }
      

  35.   

    BLL层中还带 链接字符串  多不优雅啊!
      

  36.   


    其实很简单。真的很简单。DA只要增加一个函数就可以了。这个函数的功能就是在SQL中抛出异常(raiseerror)
      

  37.   

    那个SqlHelper.BeginTransaction(sqlconnection conn)
    的方法内容是什么?