近期的一次面试当中聊起了 .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中找到。