最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

利用AOP實現(xiàn)SqlSugar自動事務(wù)

 更新時間:2017年10月26日 14:48:03   作者:若若若邪  
這篇文章主要為大家詳細(xì)介紹了利用AOP實現(xiàn)SqlSugar自動事務(wù),具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了如何利用AOP實現(xiàn)SqlSugar自動事務(wù),供大家參考,具體內(nèi)容如下

先看一下效果,帶接口層的三層架構(gòu):

BL層:

 public class StudentBL : IStudentService
   {
     private ILogger mLogger;
     private readonly IStudentDA mStudentDa;
     private readonly IValueService mValueService;

     public StudentService(IStudentDA studentDa,IValueService valueService)
     {
       mLogger = LogManager.GetCurrentClassLogger();
       mStudentDa = studentDa;
       mValueService = valueService;

     }

     [TransactionCallHandler]
     public IList<Student> GetStudentList(Hashtable paramsHash)
     {
       var list = mStudentDa.GetStudents(paramsHash);
       var value = mValueService.FindAll();
       return list;
     }
   }

假設(shè)GetStudentList方法里的mStudentDa.GetStudents和mValueService.FindAll不是查詢操作,而是更新操作,當(dāng)一個失敗另一個需要回滾,就需要在同一個事務(wù)里,當(dāng)一個出現(xiàn)異常就要回滾事務(wù)。

特性TransactionCallHandler就表明當(dāng)前方法需要開啟事務(wù),并且當(dāng)出現(xiàn)異常的時候回滾事務(wù),方法執(zhí)行完后提交事務(wù)。

DA層:

 public class StudentDA : IStudentDA
   {

     private SqlSugarClient db;
     public StudentDA()
     {
       db = SugarManager.GetInstance().SqlSugarClient;
     }
     public IList<Student> GetStudents(Hashtable paramsHash)
     {
       return db.Queryable<Student>().AS("T_Student").With(SqlWith.NoLock).ToList();
     }
   }

對SqlSugar做一下包裝

 public class SugarManager
   {
     private static ConcurrentDictionary<string,SqlClient> _cache =
       new ConcurrentDictionary<string, SqlClient>();
     private static ThreadLocal<string> _threadLocal;
     private static readonly string _connStr = @"Data Source=localhost;port=3306;Initial Catalog=thy;user id=root;password=xxxxxx;Charset=utf8";
     static SugarManager()
     {
       _threadLocal = new ThreadLocal<string>();
     }

     private static SqlSugarClient CreatInstance()
     {
       SqlSugarClient client = new SqlSugarClient(new ConnectionConfig()
       {
         ConnectionString = _connStr, //必填
         DbType = DbType.MySql, //必填
         IsAutoCloseConnection = true, //默認(rèn)false
         InitKeyType = InitKeyType.SystemTable
       });
       var key=Guid.NewGuid().ToString().Replace("-", "");
       if (!_cache.ContainsKey(key))
       {
         _cache.TryAdd(key,new SqlClient(client));
         _threadLocal.Value = key;
         return client;
       }
       throw new Exception("創(chuàng)建SqlSugarClient失敗");
     }
     public static SqlClient GetInstance()
     {
       var id= _threadLocal.Value;
       if (string.IsNullOrEmpty(id)||!_cache.ContainsKey(id))
         return new SqlClient(CreatInstance());
       return _cache[id];
     }


     public static void Release()
     {
       try
       {
         var id = GetId();
         if (!_cache.ContainsKey(id))
           return;
         Remove(id);
       }
       catch (Exception e)
       {
         throw e;
       }
     }
     private static bool Remove(string id)
     {
       if (!_cache.ContainsKey(id)) return false;

       SqlClient client;

       int index = 0;
       bool result = false;
       while (!(result = _cache.TryRemove(id, out client)))
       {
         index++;
         Thread.Sleep(20);
         if (index > 3) break;
       }
       return result;
     }
     private static string GetId()
     {
       var id = _threadLocal.Value;
       if (string.IsNullOrEmpty(id))
       {
         throw new Exception("內(nèi)部錯誤: SqlSugarClient已丟失.");
       }
       return id;
     }

     public static void BeginTran()
     {
       var instance=GetInstance();
       //開啟事務(wù)
       if (!instance.IsBeginTran)
       {
         instance.SqlSugarClient.Ado.BeginTran();
         instance.IsBeginTran = true;
       }
     }

     public static void CommitTran()
     {
       var id = GetId();
       if (!_cache.ContainsKey(id))
         throw new Exception("內(nèi)部錯誤: SqlSugarClient已丟失.");
       if (_cache[id].TranCount == 0)
       {
         _cache[id].SqlSugarClient.Ado.CommitTran();
         _cache[id].IsBeginTran = false;
       }
     }

     public static void RollbackTran()
     {
       var id = GetId();
       if (!_cache.ContainsKey(id))
         throw new Exception("內(nèi)部錯誤: SqlSugarClient已丟失.");
       _cache[id].SqlSugarClient.Ado.RollbackTran();
       _cache[id].IsBeginTran = false;
       _cache[id].TranCount = 0;
     }

     public static void TranCountAddOne()
     {
       var id = GetId();
       if (!_cache.ContainsKey(id))
         throw new Exception("內(nèi)部錯誤: SqlSugarClient已丟失.");
       _cache[id].TranCount++;
     }
     public static void TranCountMunisOne()
     {
       var id = GetId();
       if (!_cache.ContainsKey(id))
         throw new Exception("內(nèi)部錯誤: SqlSugarClient已丟失.");
       _cache[id].TranCount--;
     }
   }

_cache保存SqlSugar實例,_threadLocal確保同一線程下取出的是同一個SqlSugar實例。

不知道SqlSugar判斷當(dāng)前實例是否已經(jīng)開啟事務(wù),所以又將SqlSugar包了一層。

 public class SqlClient
   {
     public SqlSugarClient SqlSugarClient;
     public bool IsBeginTran = false;
     public int TranCount = 0;

     public SqlClient(SqlSugarClient sqlSugarClient)
     {
       this.SqlSugarClient = sqlSugarClient;
     }
   }

IsBeginTran標(biāo)識當(dāng)前SqlSugar實例是否已經(jīng)開啟事務(wù),TranCount是一個避免事務(wù)嵌套的計數(shù)器。

一開始的例子

 [TransactionCallHandler]
      public IList<Student> GetStudentList(Hashtable paramsHash)
      {
        var list = mStudentDa.GetStudents(paramsHash);
        var value = mValueService.FindAll();
        return list;
      }

TransactionCallHandler表明該方法要開啟事務(wù),但是如果mValueService.FindAll也標(biāo)識了TransactionCallHandler,又要開啟一次事務(wù)?所以用TranCount做一個計數(shù)。

使用Castle.DynamicProxy

要實現(xiàn)標(biāo)識了TransactionCallHandler的方法實現(xiàn)自動事務(wù),使用Castle.DynamicProxy實現(xiàn)BL類的代理

Castle.DynamicProxy一般操作

 public class MyClass : IMyClass
  {
    public void MyMethod()
    {
      Console.WriteLine("My Mehod");
    }
 }
 public class TestIntercept : IInterceptor
   {
     public void Intercept(IInvocation invocation)
     {
       Console.WriteLine("before");
       invocation.Proceed();
       Console.WriteLine("after");
     }
   }

  var proxyGenerate = new ProxyGenerator();
  TestIntercept t=new TestIntercept();
  var pg = proxyGenerate.CreateClassProxy<MyClass>(t);
  pg.MyMethod();
  //輸出是
  //before
  //My Mehod
  //after

before就是要開啟事務(wù)的地方,after就是提交事務(wù)的地方

最后實現(xiàn)

 public class TransactionInterceptor : IInterceptor
   {
     private readonly ILogger logger;
     public TransactionInterceptor()
     {
       logger = LogManager.GetCurrentClassLogger();
     }
     public void Intercept(IInvocation invocation)
     {
       MethodInfo methodInfo = invocation.MethodInvocationTarget;
       if (methodInfo == null)
       {
         methodInfo = invocation.Method;
       }

       TransactionCallHandlerAttribute transaction =
         methodInfo.GetCustomAttributes<TransactionCallHandlerAttribute>(true).FirstOrDefault();
       if (transaction != null)
       {
         SugarManager.BeginTran();
         try
         {
           SugarManager.TranCountAddOne();
           invocation.Proceed();
           SugarManager.TranCountMunisOne();
           SugarManager.CommitTran();
         }
         catch (Exception e)
         {
           SugarManager.RollbackTran();
           logger.Error(e);
           throw e;
         }

       }
       else
       {
         invocation.Proceed();
       }
     }
   }
   [AttributeUsage(AttributeTargets.Method, Inherited = true)]
   public class TransactionCallHandlerAttribute : Attribute
   {
     public TransactionCallHandlerAttribute()
     {

     }
   }

Autofac與Castle.DynamicProxy結(jié)合使用

創(chuàng)建代理的時候一個BL類就要一次操作

 proxyGenerate.CreateClassProxy<MyClass>(t);

而且項目里BL類的實例化是交給IOC容器控制的,我用的是Autofac。當(dāng)然Autofac和Castle.DynamicProxy是可以結(jié)合使用的

using System.Reflection;
using Autofac;
using Autofac.Extras.DynamicProxy;
using Module = Autofac.Module;
public class BusinessModule : Module
  {
    protected override void Load(ContainerBuilder builder)
    {
      var business = Assembly.Load("FTY.Business");
      builder.RegisterAssemblyTypes(business)
        .AsImplementedInterfaces().InterceptedBy(typeof(TransactionInterceptor)).EnableInterfaceInterceptors();
      builder.RegisterType<TransactionInterceptor>();
    }
  }

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#實現(xiàn)的鼠標(biāo)鉤子

    C#實現(xiàn)的鼠標(biāo)鉤子

    本文給大家分享的是使用C#實現(xiàn)鼠標(biāo)鉤子功能,程序已能獲取鼠標(biāo)坐標(biāo),其他就沒別的功能了,有需要的小伙伴參考下吧。
    2015-03-03
  • C#連接SQL?Sever數(shù)據(jù)庫與數(shù)據(jù)查詢實例之?dāng)?shù)據(jù)倉庫詳解

    C#連接SQL?Sever數(shù)據(jù)庫與數(shù)據(jù)查詢實例之?dāng)?shù)據(jù)倉庫詳解

    最近的工作遇到了連接查詢,特在此記錄,以免日后以往,下面這篇文章主要給大家介紹了關(guān)于C#連接SQL?Sever數(shù)據(jù)庫與數(shù)據(jù)查詢實例之?dāng)?shù)據(jù)倉庫的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • VisualStudio2019安裝C#環(huán)境的實現(xiàn)方法

    VisualStudio2019安裝C#環(huán)境的實現(xiàn)方法

    這篇文章主要介紹了VisualStudio2019安裝C#環(huán)境的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • C#畫圓角矩形的方法

    C#畫圓角矩形的方法

    這篇文章主要介紹了C#畫圓角矩形的方法,涉及C#繪圖的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-05-05
  • C#構(gòu)造函數(shù)在基類和父類中的執(zhí)行順序

    C#構(gòu)造函數(shù)在基類和父類中的執(zhí)行順序

    這篇文章介紹了C#構(gòu)造函數(shù)在基類和父類中的執(zhí)行順序,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • C#獲取文件名和文件路徑的兩種實現(xiàn)方式

    C#獲取文件名和文件路徑的兩種實現(xiàn)方式

    這篇文章主要介紹了C#獲取文件名和文件路徑的兩種實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • C# 預(yù)處理器指令的用法

    C# 預(yù)處理器指令的用法

    本文主要介紹了C# 預(yù)處理器指令的用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Visual Studio連接unity編輯器的實現(xiàn)步驟

    Visual Studio連接unity編輯器的實現(xiàn)步驟

    unity編輯器中打開C#腳本的時候發(fā)現(xiàn)Visual Studio沒有連接unity編輯器,本文主要介紹了Visual Studio連接unity編輯器的實現(xiàn)步驟,感興趣的可以了解一下
    2023-11-11
  • C#使用listView增刪操作實例

    C#使用listView增刪操作實例

    這篇文章主要介紹了C#使用listView增刪操作的實現(xiàn)方法,實例分析了C#中使用listView控件進(jìn)行動態(tài)添加、選中刪除等操作的技巧,具有一定的參考借鑒價值,需要的朋友可以參考下
    2014-12-12
  • C#實現(xiàn)只運行單個實例應(yīng)用程序的方法(使用VB.Net的IsSingleInstance)

    C#實現(xiàn)只運行單個實例應(yīng)用程序的方法(使用VB.Net的IsSingleInstance)

    這篇文章主要介紹了C#實現(xiàn)只運行單個實例應(yīng)用程序的方法,本文使用的是VB.Net的IsSingleInstance方法實現(xiàn),優(yōu)于Mutex 和 Process 這兩種只運行單個應(yīng)用程序?qū)嵗姆椒?需要的朋友可以參考下
    2014-07-07

最新評論

安福县| 岑溪市| 湾仔区| 通山县| 大关县| 司法| 老河口市| 紫云| 盐山县| 安丘市| 博罗县| 蒙自县| 西乌珠穆沁旗| 武平县| 宁阳县| 舟山市| 铜鼓县| 奈曼旗| 咸阳市| 内江市| 卫辉市| 准格尔旗| 珲春市| 柳河县| 刚察县| 汉源县| 翁牛特旗| 纳雍县| 泰来县| 西和县| 新田县| 新晃| 四平市| 开江县| 东丽区| 青州市| 云阳县| 台北市| 多伦县| 东明县| 巴东县|