.NET Core2.0 实现Slickflow.NET开源工作流引擎

2018 年 4 月 4 日 DotNet

(点击上方蓝字,可快速关注我们)


来源:slickflowteam

cnblogs.com/slickflow/p/8250317.html


前言


.NET Core 是.NET Framework的新一代版本,是微软开发的第一个跨平台 (Windows、Mac OSX、Linux) 的应用程序开发框架(Application Framework),未来也将会支持 FreeBSD 与 Alpine 平台。


.NET Core也是微软在一开始发展时就开源的软件平台,其开发目标是跨平台的 .NET 平台。


.NET Core 平台的开发优势 :


  1. 支持或可以移转 (port) 到更多的操作系统平台与芯片架构 (也就是未来项目会跨出 x86 平台)。


  2. 具有引人注目的性能与高可靠度。


  3. 开发人员能快速与直觉的获取 .NET Core 开发环境。


  4. 在直觉与具生产力的情况下建造应用程序,使用文件,示例与 NuGet 组件。


以上文字引用来源:https://zh.wikipedia.org/wiki/.NET_Core


一、.NET Core 2.0 迁移指南


由于.NET Core跨平台开发和性能方面的优势,再加上.NET Core2.0版本的推出,越来越多的客户逐渐迁移到.NET Core框架进行软件系统的开发。Slickflow引擎组件的.NET Core版本的推出,也是为了解决跨平台引擎产品的实现。


本文大致描述了创建.NET Core2.0 为目标版本类库,数据访问项目和Asp.NET Mvc Core等类型项目的搭建过程,方便用户快速上手。


1.1、数据访问项目


1)  IRepository模式实现


Repository模式实现通用数据访问接口,其好处是首先定义出标准的增删改查接口,其次可以满足对接后端不同的数据处理框架,如Dapper,EF和NHibernate等框架。


/// <summary>

/// 数据操作类接口

/// </summary>

/// <typeparam name="T">数据实体类型</typeparam>

public interface IRepository<T> where T : class

{

    DbSet<T> GetDbSet();


    T GetByID(dynamic id);

    T Get(Expression<Func<T, bool>> predicate);

    IQueryable<T> GetAll();


    IQueryable<T> Query(string sql, params object[] parameters);

    IEnumerable<T> Query(Expression<Func<T, bool>> predicate);

    int Count(Expression<Func<T, bool>> predicate = null);



    //insert, update, delete

    T Insert(T entity);

    void Insert(params T[] entities);

    void Insert(IEnumerable<T> entities);

    void Update(T entity);

    void Update(params T[] entities);

    void Update(IEnumerable<T> entities);

    void Delete(dynamic id);

    void Delete(params T[] entities);

    void Delete(IEnumerable<T> entities);

}


2)  UnitOfWork 解决事务


引擎内部逻辑处理通常是多表的插入编辑操作,为保持数据事务完整性,需要实现会话事务的参数传递,提供提交和回滚的处理方式。Slickflow.Data.IDbSession用来实现UnitOfWork模式。


/// <summary>

/// 数据会话接口

/// </summary>

public interface IDbSession : IDisposable

{

    DbContext DbContext { get; }

    IRepository<T> GetRepository<T>() where T : class;

    int SaveChanges();

    int ExecuteSqlCommand(string sql, params object[] paramters);

}


代码示例:Session作为参数,传入具体接口方法,最终实现事务的一致提交或回滚。


/// <summary>

///  运行流程测试

/// </summary>

/// <param name="runner">运行者</param>

/// <returns>执行结果</returns>

[HttpPost]

public ResponseResult RunProcessApp([FromBody] WfAppRunner runner)

{

    using (var session = DbFactory.CreateSession())

    {

        var transaction = session.DbContext.Database.BeginTransaction();

        var wfService = new WorkflowService();

        var result = wfService.RunProcessApp(runner, session);


        if (result.Status == WfExecutedStatus.Success)

        {

            transaction.Commit();

            return ResponseResult.Success();

        }

        else

        {

            transaction.Rollback();

            return ResponseResult.Error(result.Message);

        }

    }

}


1.2、ASP.NET MVC Core项目


1)  Mvc和WebAPI路由统一配置


通常在.NET项目开发中,Mvc项目用于前端页面展现,WebAPI用于后端接口实现。在项目实践过程中,可以将两个项目整合为一,便于环境配置。


app.UseMvc(route => {

                route.MapRoute(

                    name: "default",

                    template: "{controller=Home}/{action=Index}/{id?}");

 

                route.MapRoute(

                    name:"defaultApi",

                    template: "api/{controller}/{action}/{id?}");

            });


2)  数据库连接串配置


数据库链接串在appsettings.json文件中进行定义,读取方法如下:


var dbType = ConfigurationExtensions.GetConnectionString(Configuration, "WfDBConnectionType");

var sqlConnectionString = ConfigurationExtensions.GetConnectionString(Configuration, "WfDBConnectionString");

 

Slickflow.Data.ConnectionString.DbType = dbType;

Slickflow.Data.ConnectionString.Value = sqlConnectionString;

3) DbContext 数据库类型匹配


由于不同类型数据库的数据访问组件不同,所以特意做了接口对应匹配,传入数据库连接串值。


protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)

{

    if (ConnectionString.DbType == DatabaseTypeEnum.SQLSERVER.ToString())

        optionsBuilder.UseSqlServer(ConnectionString.Value);

    else if (ConnectionString.DbType == DatabaseTypeEnum.MYSQL.ToString())

        optionsBuilder.UseMySql(ConnectionString.Value);

    else if (ConnectionString.DbType == DatabaseTypeEnum.ORACLE.ToString())

        optionsBuilder.UseOracle(ConnectionString.Value);

}


二、EF Core对多数据库生成的支持


EF Code First是由实体来生成数据库模型,简要过程描述为:首先定义好实体对象,对应数据库字段类型,然后执行EF Migrations的操作命令来生成数据库对象。其中经常用到的命令有:


   1) dotnet ef migrations add MyFirstMigraton


   2) dotnet ef migrations update database


下面就以WfProcess表的创建来说明大致的创建过程。


2.1 MS SQLSERVER数据库


采用的数据访问组件默认为:Microsoft.EntityFrameworkCore。


1)  实体属性标识


  /// <summary>

   /// 流程实体类

   /// </summary>

   [Table("WfProcess")]

   public class ProcessEntity

   {

       [Key]

       [DatabaseGenerated(DatabaseGeneratedOption.Identity)]

       [Column(Order = 0)]

       public int ID { get; set; }

 

       [Required]

       [Column(TypeName = "varchar(100)", Order = 1)]

       [MaxLength(100)]

       public string ProcessGUID { get; set; }

 

       [Required]

       [Column(TypeName = "nvarchar(50)", Order = 2)]

       [MaxLength(50)]

       public string ProcessName { get; set; }

 

       [Required]

       [Column(TypeName ="nvarchar(20)", Order = 3)]

       [MaxLength(20)]

       public string Version { get; set; }

   }


2)  默认值赋值


//流程创建

modelBuilder.Entity<ProcessEntity>(entity =>

{

    entity.Property(e => e.Version).HasDefaultValue("1");

    entity.Property(e => e.IsUsing).HasDefaultValue(0);

    entity.Property(e => e.StartType).HasDefaultValue(0);

    entity.Property(e => e.EndType).HasDefaultValue(0);

    entity.Property(e => e.CreatedDateTime).HasDefaultValueSql("getdate()");

});


3)  生成命令执行


dotnet ef migrations add MyFirstMigration


2.2、MySQL数据库


采用的数据访问组件默认为:Polemo.EntityFrameworkCore.MySQL。


1)  实体属性标识


/// <summary>

/// 流程实体类

/// </summary>

[Table("WfProcess")]

public class ProcessEntity

{

    [Key]

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]

    [Column(Order = 0)]

    public int ID { get; set; }

 

    [Required]

    [Column(TypeName = "varchar(100)", Order = 1)]

    [MaxLength(100)]

    public string ProcessGUID { get; set; }

 

    [Required]

    [Column(TypeName = "varchar(50)", Order = 2)]

    [MaxLength(50)]

    public string ProcessName { get; set; }

 

    [Required]

    [Column(TypeName ="varchar(20)", Order = 3)]

    [MaxLength(20)]

    public string Version { get; set; }

}


2)  默认值赋值


//流程创建

modelBuilder.Entity<ProcessEntity>(entity =>

{

    entity.Property(e => e.Version).HasDefaultValue("1");

    entity.Property(e => e.IsUsing).HasDefaultValue(0);

    entity.Property(e => e.StartType).HasDefaultValue(0);

    entity.Property(e => e.EndType).HasDefaultValue(0);

});


3) 生成命令执行


dotnet ef migrations add MyFirstMigration


三、Slickflow.WebAPI 快速测试


 3.1、路由模式选定:


仍然选定传统路由模式,便于接口快速识别和匹配。


app.UseMvc(route => {

    route.MapRoute(

        name: "defaultApi",

        template: "api/{controller}/{action}/{id?}");

});


3.2 、数据库链接串读取:


var dbType = ConfigurationExtensions.GetConnectionString(Configuration, "WfDBConnectionType");

var sqlConnectionString = ConfigurationExtensions.GetConnectionString(Configuration, "WfDBConnectionString");

 

Slickflow.Data.ConnectionString.DbType = dbType;

Slickflow.Data.ConnectionString.Value = sqlConnectionString;


3.3、测试接口方法


/// <summary>

///  启动流程测试

/// </summary>

/// <param name="runner">运行者</param>

/// <returns>执行结果</returns>

[HttpPost]

public ResponseResult StartProcess([FromBody] WfAppRunner runner)

{

    using (var session = DbFactory.CreateSession())

    {

        var transaction = session.DbContext.Database.BeginTransaction();

        var wfService = new WorkflowService();

        var result = wfService.StartProcess(runner, session);

 

        if (result.Status == WfExecutedStatus.Success)

        {

            transaction.Commit();

            return ResponseResult.Success();

        }

        else

        {

            transaction.Rollback();

            return ResponseResult.Error(result.Message);

        }

    }

}


3.4、RestClient 测试工具


引擎接口测试采用RestClient工具,比较方便快捷。通常采用统一的接口方法,将不同类型的流程JSON数据格式作为测试用例来提交测试。



四、总结


Slickflow 引擎产品的.NET Core版本实现,用于跨平台应用的项目开发和业务集成。而且在数据库的支持上,采用EF Core的Code First数据库迁移创建,方便用户开发环境的快速搭建和配置。


看完本文有收获?请转发分享给更多人

关注「DotNet」,提升.Net技能 

淘口令复制以下红色内容,再打开手淘即可购买

范品社,使用¥极客T恤¥抢先预览(长按复制整段文案,打开手机淘宝即可进入活动内容)

登录查看更多
1

相关内容

.NET 框架(.NET Framework) 是由微软开发,一个致力于敏捷软件开发、快速应用开发、平台无关性和网络透明化的软件开发平台。
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
《强化学习—使用 Open AI、TensorFlow和Keras实现》174页pdf
专知会员服务
136+阅读 · 2020年3月1日
【新书】Java企业微服务,Enterprise Java Microservices,272页pdf
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
Keras作者François Chollet推荐的开源图像搜索引擎项目Sis
专知会员服务
29+阅读 · 2019年10月17日
TensorFlow 2.0 学习资源汇总
专知会员服务
66+阅读 · 2019年10月9日
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
如何编写完美的 Python 命令行程序?
CSDN
5+阅读 · 2019年1月19日
TF Boys必看!一文搞懂TensorFlow 2.0新架构!
引力空间站
18+阅读 · 2019年1月16日
.NET Core 环境下构建强大且易用的规则引擎
开源巨献:阿里巴巴最热门29款开源项目
算法与数据结构
5+阅读 · 2017年7月14日
Arxiv
5+阅读 · 2018年10月23日
Arxiv
3+阅读 · 2018年5月28日
Arxiv
7+阅读 · 2017年12月28日
Arxiv
5+阅读 · 2017年7月23日
VIP会员
相关资讯
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
如何编写完美的 Python 命令行程序?
CSDN
5+阅读 · 2019年1月19日
TF Boys必看!一文搞懂TensorFlow 2.0新架构!
引力空间站
18+阅读 · 2019年1月16日
.NET Core 环境下构建强大且易用的规则引擎
开源巨献:阿里巴巴最热门29款开源项目
算法与数据结构
5+阅读 · 2017年7月14日
Top
微信扫码咨询专知VIP会员