1、定义Dto 和 Grpc协议
namespace MagicProtocal.Dto { public class Usr { public int Id { get; set; } public string Code { get; set; } public string Name { get; set; } } } namespace MagicProtocal.Protocal { public interface IUsrSvc : MagicOnion.IService<IUsrSvc> { MagicOnion.UnaryResult<List<Usr>> GetUsrs(); } }
2、业务服务实现,可能被WebApi用,也可能被Grpc用
public class IsServiceAttribute:System.Attribute { } [IsService] public class DbContxt: DbContext { static string connStr = null; static DbContxt() { if (connStr == null) { connStr = "000000000000000"; } } public DbContxt() { ConnectionString(connStr, new MySqlProvider(), MySql.Data.MySqlClient.MySqlClientFactory.Instance); Data.IgnoreIfAutoMapFails = true; } } public class BaseSvc { public DbContxt Db { get; set; } } [IsService] public class DeptSvc: BaseSvc { public List<Usr> GetUsrsTop10() { Console.WriteLine($"DeptSvc DbHashCode: {Db.GetHashCode()},UseTransaction:{Db.Data.UseTransaction}"); return Db.Sql("SELECT id, CODE, NAME FROM employee limit 10").QueryMany<Usr>(); } } public interface IUsrService { List<Usr> GetUsrs(); int AddCity(string city); List<Usr> GetUsrsTop10(); } [IsService] public class UsrService: BaseSvc, IUsrService { public DeptSvc DeptSvc { get; set; } public int AddCity(string city) { Console.WriteLine($"AddCity DbHashCode: {Db.GetHashCode()},UseTransaction:{Db.Data.UseTransaction}"); return Db.Insert("testcity").Column("Name", city).Execute(); } public List<Usr> GetUsrs() { Console.WriteLine($"GetUsrs DbHashCode: {Db.GetHashCode()},UseTransaction:{Db.Data.UseTransaction}"); return Db.Sql("SELECT id, CODE, NAME FROM employee").QueryMany<Usr>(); } public List<Usr> GetUsrsTop10() { return DeptSvc.GetUsrsTop10(); } }
3、服务端使用Autofac 并保证事务
public static class ContainerManager { static IContainer container; static ContainerManager() { Autofac.ContainerBuilder builder = new Autofac.ContainerBuilder(); var types = typeof(BaseSvc).Assembly.GetTypes(); foreach (var typ in types) { var typeInfo = typ.GetTypeInfo(); if (typeInfo.IsDefined(typeof(IsServiceAttribute))) { builder.RegisterType(typ).InstancePerLifetimeScope().AsSelf().AsImplementedInterfaces().PropertiesAutowired(); var interfaces = typeInfo.ImplementedInterfaces; foreach (var item in interfaces) { builder.RegisterType(typ).As(item).InstancePerLifetimeScope().AsSelf().AsImplementedInterfaces().PropertiesAutowired(); } } } container = builder.Build(); } public static ILifetimeScope Scope() { ILifetimeScope agent = container.BeginLifetimeScope(); var db = agent.Resolve<DbContxt>().UseTransaction(true); Console.WriteLine("已开启事务:" + db.GetHashCode()); return agent; } public static void Commit(this ILifetimeScope scope) { var db = scope.Resolve<DbContxt>().Commit(); Console.WriteLine("事务已提交:" + db.GetHashCode()); } } class Program { static void Main(string[] args) { var service = MagicOnionEngine.BuildServerServiceDefinition( new Assembly[] { typeof(Program).Assembly }, new MagicOnionOptions(false) { MagicOnionLogger = new MagicOnionLogToGrpcLogger(), SerializerOptions = MessagePackSerializerOptions.Standard.WithResolver( MessagePack.Resolvers.ContractlessStandardResolverAllowPrivate.Instance), IsReturnExceptionStackTraceInErrorDetail=true }); Server server = new Server { Services = { service }, Ports = { new ServerPort("localhost", 5555, ServerCredentials.Insecure) }, }; server.Start(); Console.WriteLine("localhost:5555 已启动"); Console.ReadLine(); } } public class MgcUsrSvc : MagicOnion.Server.ServiceBase<IUsrSvc>, IUsrSvc { public MagicOnion.UnaryResult<List<Usr>> GetUsrs() { using (var scope = ContainerManager.Scope()) { var usrSvc = scope.Resolve<IUsrService>(); var usrs = usrSvc.GetUsrs(); var id = usrSvc.AddCity("00009"); var usr10 = scope.Resolve<DeptSvc>().GetUsrsTop10(); usr10 = usrSvc.GetUsrsTop10(); scope.Commit(); return new MagicOnion.UnaryResult<List<Usr>>(usr10); } } }
4、打印测试事务