近期的一次面试当中聊起了 .Net Core 中的 EF 框架和分布式的事务,因为在项目中也遇到过并发导致 EF Core 性能和报错的各种问题,所以就和面试官吐槽了一下,面试官说他们公司用的 SqlSugar 。这个开源组件库我以前知道的,但很久没有关注。回家看了一下发现这个东西已经非常完善,特此将项目中的 EF Core 变更为了 SqlSugar并且加入了 Cap,顺便记录一下遇到的问题。
 1. SqlSugar简介
   SqlSugar是一款 老牌 .NET 开源ORM框架,由果糖大数据科技团队维护和更新 ,Github star数仅次于EF 和 Dapper。优点: 简单易用、功能齐全、高性能、轻量级、服务齐全、有专业技术支持一天18小时服务。支持数据库有 MySql、SqlServer、Sqlite、Oracle 、 postgresql、达梦、人大金仓。我的项目习惯了Code First,第一次使用也不知道是否正确。
Startup.cs - SqlSugar 注入代码
1 2 3 4 5 6 7 8 9
   | services.AddTransient<OdinProjectSugarDbContext>(); OdinInjectHelper.ServiceProvider = services.BuildServiceProvider(); var sugarEntity = OdinInjectHelper.GetService<OdinProjectSugarDbContext>(); #region 初始化数据库
  if (_Options.DbEntity.InitDb) { 	sugarEntity.CreateTable("db_odinCore", false); }
   | 
OdinProjectSugarDbContext.cs - DbContext定义以及初始化数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
   | public class OdinProjectSugarDbContext {     SqlSugarClient db;     public OdinProjectSugarDbContext()     {         db = DbScoped.Sugar;     }     public void CreateTable(string databaseName, bool Backup = false)     {
          var flag = false;         try         {	                          flag = db.DbMaintenance.GetDataBaseList(db).Contains(databaseName);         }         catch         {                          db.DbMaintenance.CreateDatabase(databaseName);         }         finally         {             if (!flag)             {                 Log.Logger.Information($"【 自动创建数据库 】");                 db.DbMaintenance.CreateDatabase(databaseName);                                  var dbTable = typeof(IDbTable);                                  var types = this.GetType().Assembly.GetTypes().Where(t => dbTable.IsAssignableFrom(t));                                  if (Backup)                 {                     foreach (var item in types)                     {                                                  if (!OdinSugarHelper.CheckTable(item))                         {                             DbScoped.Sugar.CodeFirst.BackupTable().InitTables(item);                             Log.Logger.Information($"创建数据表【 {item.ToString()} 】");                         }
                      }
                  }                 else                 {                     foreach (var item in types)                     {                         if (!OdinSugarHelper.CheckTable(item))                         {                             DbScoped.Sugar.CodeFirst.InitTables(item);                             Log.Logger.Information($"创建数据表【 {item.ToString()} 】");                         }                     }
                  }                 Log.Logger.Information($"启用【 数据库初始化 】---开始配置");                 SampleData.Init();             }         }     }
      public OdinSugarDbSet<Aop_ApiInvokerCatch_DbModel> ApiInvokerCatchs { get { return new OdinSugarDbSet<Aop_ApiInvokerCatch_DbModel>(db); } }
      public OdinSugarDbSet<Aop_ApiInvokerRecord_DbModel> ApiInvokerRecords { get { return new OdinSugarDbSet<Aop_ApiInvokerRecord_DbModel>(db); } }
      public OdinSugarDbSet<ErrorCode_DbModel> ErrorCodes { get { return new OdinSugarDbSet<ErrorCode_DbModel>(db); } } }
   | 
OdinSugarHelper.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
   | public class OdinSugarHelper {     static SqlSugarClient Db = DbScoped.Sugar;                              public static bool CheckTable(Type type)     {         string tableName = Db.EntityMaintenance.GetTableName(type);         return Db.DbMaintenance.IsAnyTable(tableName, false);     }
                               public static bool CheckTable<T>()     {         string tableName = Db.EntityMaintenance.GetTableName(typeof(T));         return Db.DbMaintenance.IsAnyTable(tableName, false);     }
                               public static bool CheckTable(string TableName)     {         return Db.DbMaintenance.IsAnyTable(TableName, false);     } }
   | 
这样程序在运行的时候就基于DbContext的定义可以在数据库新建表。
 2. 基于 SqlSugar 使用 cap
  CAP 是一个在分布式系统中(SOA,MicroService)实现事件总线及最终一致性(分布式事务)的一个开源的 C# 库,她具有轻量级,高性能,易使用等特点。
Startup.cs - SqlSugar 注入代码
1
   | services.AddOdinCapInject(_Options.DbEntity.ConnectionString, _Options.MongoDb.MongoConnection, _Options.RabbitMQ);
   | 
AddOdinCapInject - 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
   | public static IServiceCollection AddOdinCapInject(this IServiceCollection services, string mysqlConnectionString, string mongoConnectionString, RabbitMQOptions rabbitMQOptions) {     services.AddCap(x =>     {
                            x.UseMySql(mysqlConnectionString);         
                   
                   x.UseRabbitMQ(rb =>         {             rb.HostName = rabbitMQOptions.HostNames[0];             rb.UserName = rabbitMQOptions.Account.UserName;             rb.Password = rabbitMQOptions.Account.Password;             rb.VirtualHost = rabbitMQOptions.VirtualHost;             rb.Port = rabbitMQOptions.Port;
          });                           x.UseDashboard();     });     return services; }
   | 
OdinCapHelper.cs - 封装,注入到service中即可使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   | public class OdinCapHelper : IOdinCapHelper {     public void CapPublish<T>(string publishName, T contentObj, Action action = null)     {         var db = DbScoped.Sugar;         var capBus = OdinInjectHelper.GetService<ICapPublisher>();         using (var connection = (MySqlConnection)db.Ado.Connection)         {             using (var transaction = connection.BeginTransaction(capBus, autoCommit: false))             {                 if (connection.State != ConnectionState.Open)                 {                     connection.Open();                 }                 db.Ado.Transaction = (IDbTransaction)transaction.DbTransaction;                 if (action != null) action();                 capBus.Publish<T>(publishName, contentObj);                 transaction.Commit();             }         }     } }
   | 
这里需要注意的是,如果和我一样是使用mysql数据库,那么需要讲nuget包由 SqlSugarCore 替换为 SqlSugarCore.MySqlConnector 切记!!! 切记!!!
** Controller ** - Action方法中发布消息
1 2 3 4 5
   | var db = DbScoped.Sugar; OdinCapHelper.CapPublish("Sample.RabbitMQ.MySql", DateTime.Now, () =>     {         System.Console.WriteLine("to do something");     });
   | 
Controller - Action方法中订阅消费消息
1 2 3 4 5 6
   | [CapSubscribe("Sample.RabbitMQ.MySql")] public async Task<Task> CheckReceivedMessage(DateTime time) {     Console.WriteLine(time);     return Task.CompletedTask; }
  | 
完整代码可以在 GitHub中找到。