Asp.Net Core 使用Quartz基于界面画接口管理做定时任务

Asp.Net Core 使用Quartz基于界面画接口管理做定时任务

  • 商品编号:
    #36603385_466
    • 原价:
      免费
    • 会员价:
      免费
  • 分类:
    • V1.0.0
  • 数量:

购物车中已存在此商品,请在购物车中操作单击跳转购物车

  • 拥有者:鸟窝
  • 开发语言:.NET Core
  • 开发环境:Visual Studio
  • 数据库:MySql
  • 商品架构:B/S
  • 代码管理工具:GitHub
  • 编码格式:UTF-8
  • 是否开源:是
  • 开源协议:BSD协议

今天抽出一点点时间来造一个小轮子,是关于定时任务这块的。

这篇文章主要从一下几点介绍:

  1. 创建数据库管理表

  2. 创建web项目

  3. 引入quarzt nuget 包

  4. 写具体配置操作,实现定时任务处理

第一步:创建一个空web项目,引入quarzt nuget 包


创建TB.AspNetCore.Quartz web项目和TB.AspNetCore.Data 类库,在web项目中引入Quartz nuget包

第二部:数据库创建一张管理表



创建数据库的表结构如图所示,接下来我们在Data项目里添加mysql数据库驱动nuget包  



打开PM,执行数据库反向工程命令,从数据库生成model实体

Scaffold-DbContext "Server=你的服务器地址;Database=你的数据库;User=数据库用户名;Password=你的数据库密码;" 
"Pomelo.EntityFrameworkCore.MySql" -OutputDir Entity

 **2.1.1 建议不要选用,防坑!


将链接字符串换成你自己的,我们又新添加了一个service文件夹和一个Enum文件夹  


其中,BaseService 里封装了针对数据操作的基本crud,quartz里封装了关于定时任务的配置,enum里枚举了任务状态,具体代码如下  


下面是baseservice里具体方法  

public class BaseService
    {
        protected static object obj = new object();
        public ggb_offlinebetaContext _context;
        protected ggb_offlinebetaContext DataContext
        {
            get
            {
                if (_context == null)
                {
                    _context = new ggb_offlinebetaContext();
                }
                return _context;
            }
        }


        public BaseService()
        {

        }

        #region 封装基crud
        /// <summary>
        /// 只能是唯一记录 多记录引发异常
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public TSource Single<TSource>(Expression<Func<TSource, bool>> predicate = null) where TSource : class
        {
            if (predicate == null)
            {
                return this.DataContext.Set<TSource>().SingleOrDefault();
            }

            return this.DataContext.Set<TSource>().SingleOrDefault(predicate);
        }
        /// <summary>
        /// 查询一条记录
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public TSource First<TSource>(Expression<Func<TSource, bool>> predicate = null) where TSource : class
        {
            if (predicate == null)
            {
                return this.DataContext.Set<TSource>().FirstOrDefault();
            }
            return this.DataContext.Set<TSource>().FirstOrDefault(predicate);
        }

        /// <summary>
        /// where条件查询
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public IQueryable<TSource> Where<TSource>(Expression<Func<TSource, bool>> predicate = null) where TSource : class
        {
            if (predicate == null)
            {
                return this.DataContext.Set<TSource>().AsQueryable();
            }
            return this.DataContext.Set<TSource>().Where(predicate);
        }

        /// <summary>
        /// 记录数
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public int Count<TSource>(Expression<Func<TSource, bool>> predicate = null)
            where TSource : class
        {
            if (predicate == null)
            {
                return this.DataContext.Set<TSource>().Count();
            }
            return this.DataContext.Set<TSource>().Count(predicate);
        }

        /// <summary>
        /// 根据条件判断记录是否存在
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="predicate"></param>
        /// <returns></returns>
        /// Any确定序列是否包含任何元素
        public bool Exists<TSource>(Expression<Func<TSource, bool>> predicate = null) where TSource : class
        {
            if (predicate == null)
            {
                return this.DataContext.Set<TSource>().Any();
            }
            return this.DataContext.Set<TSource>().Any(predicate);
        }

        /// <summary>
        /// 查询全部
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <returns></returns>
        public IQueryable<TSource> Query<TSource>()
            where TSource : class
        {
            return this.DataContext.Set<TSource>();
        }

        /// <summary>
        /// paging the query 分页查询
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="query"></param>
        /// <param name="pageIndex">page index</param>
        /// <param name="pageSize">page size </param>
        /// <param name="count">total row record count</param>
        /// <returns></returns>
        public IQueryable<T> Pages<T>(IQueryable<T> query, int pageIndex, int pageSize, out int count) where T : class
        {
            if (pageIndex < 1)
            {
                pageIndex = 1;
            }
            if (pageSize < 1)
            {
                pageSize = 10;
            }
            count = query.Count();
            query = query.Skip((pageIndex - 1) * pageSize).Take(pageSize);
            return query;
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public IQueryable<T> Pages<T>(int pageIndex, int pageSize, out int count) where T : class
        {
            if (pageIndex < 1)
            {
                pageIndex = 1;
            }
            if (pageSize < 1)
            {
                pageSize = 10;
            }
            var query = this.DataContext.Set<T>().AsQueryable();
            count = query.Count();
            query = query.Skip((pageIndex - 1) * pageSize).Take(pageSize);
            return query;
        }
        #endregion

        /// <summary>
        /// 做一次提交
        /// </summary>
        #region Save Changes
        public void Save()
        {
            //todo 需要验证是否需要释放
            using (this.DataContext)
            {
                this.DataContext.SaveChanges();
            }
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="save"></param>
        public void Add(object entity, bool save = false)
        {
            this.DataContext.Add(entity);
            if (save)
            {
                this.Save();
            }
        }

        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="save"></param>
        public void Update(object entity, bool save = false)
        {
            this.DataContext.Update(entity);
            if (save)
            {
                this.Save();
            }
        }
        /// <summary>
        /// 更新2
        /// </summary>
        /// <param name="list"></param>
        /// <param name="save"></param>
        public void Update(IEnumerable<object> list, bool save = false)
        {
            this.DataContext.UpdateRange(list);
            if (save)
            {
                this.Save();
            }
        }
        /// <summary>
        /// 删除1
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="save"></param>
        public void Delete(object entity, bool save = false)
        {
            this.DataContext.Remove(entity);
            if (save)
            {
                this.Save();
            }
        }
        /// <summary>
        /// 删除2
        /// </summary>
        /// <param name="list"></param>
        /// <param name="save"></param>
        public void Delete(IEnumerable<object> list, bool save = false)
        {
            this.DataContext.RemoveRange(list);
            if (save)
            {
                this.Save();
            }
        }
        #endregion

        ///// <summary>
        ///// 释放资源
        ///// </summary>
        //public void Dispose()
        //{
        //    _context.Dispose();
        //}
    }

下面是任务调度中心代码  

/// <summary>
    /// 任务调度中心
    /// </summary>
    public class JobCenter
    {
        /// <summary>
        /// 任务计划
        /// </summary>
        public static IScheduler scheduler = null;
        public static async Task<IScheduler> GetSchedulerAsync()
        {
            if (scheduler != null)
            {
                return scheduler;
            }
            else
            {
                ISchedulerFactory schedf = new StdSchedulerFactory();
                IScheduler sched = await schedf.GetScheduler();
                return sched;
            }
        }
        /// <summary>
        /// 添加任务计划//或者进程终止后的开启
        /// </summary>
        /// <returns></returns>
        public async Task<bool> AddScheduleJobAsync(ScheduleInfo m)
        {
            try
            {
                if (m != null)
                {
                    if (m.StarRunTime == null)
                    {
                        m.StarRunTime = DateTime.Now;
                    }
                    DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(m.StarRunTime, 1);
                    if (m.EndRunTime == null)
                    {
                        m.EndRunTime = DateTime.MaxValue.AddDays(-1);
                    }
                    DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(m.EndRunTime, 1);
                    scheduler = await GetSchedulerAsync();
                    IJobDetail job = JobBuilder.Create<HttpJob>()
                      .WithIdentity(m.JobName, m.JobGroup)
                      .Build();
                    ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
                                                 .StartAt(starRunTime)
                                                 .EndAt(endRunTime)
                                                 .WithIdentity(m.JobName, m.JobGroup)
                                                 .WithCronSchedule(m.CromExpress)
                                                 .Build();
                    //将信息写入
                    new ScheduleManage().AddSchedule(m);
                    await scheduler.ScheduleJob(job, trigger);
                    await scheduler.Start();
                    await StopScheduleJobAsync(m.JobGroup, m.JobName);
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                //MyLogger.WriteError(ex, null);
                return false;
            }
        }

        /// <summary>
        /// 暂停指定任务计划
        /// </summary>
        /// <returns></returns>
        public async Task<string> StopScheduleJobAsync(string jobGroup, string jobName)
        {
            try
            {
                scheduler = await GetSchedulerAsync();
                //使任务暂停
                await scheduler.PauseJob(new JobKey(jobName, jobGroup));
                //更新数据库
                new ScheduleManage().UpdateScheduleStatus(new ScheduleInfo() { JobName = jobName, JobGroup = jobGroup, RunStatus = (int)JobStatus.已停止 });
                var status = new StatusViewModel()
                {
                    Status = 0,
                    Msg = "暂停任务计划成功",
                };

                return JsonConvert.SerializeObject(status);
            }
            catch (Exception ex)
            {
                //MyLogger.WriteError(ex, null);
                var status = new StatusViewModel()
                {
                    Status = -1,
                    Msg = "暂停任务计划失败",
                };
                return JsonConvert.SerializeObject(status);
            }
        }
        /// <summary>
        /// 恢复指定的任务计划**恢复的是暂停后的任务计划,如果是程序奔溃后 或者是进程杀死后的恢复,此方法无效
        /// </summary>
        /// <returns></returns>
        public async Task<string> RunScheduleJobAsync(string jobGroup, string jobName)
        {
            try
            {
                //获取model
                var sm = new ScheduleManage().GetScheduleModel(new ScheduleInfo() { JobName = jobName, JobGroup = jobGroup });
                await AddScheduleJobAsync(sm);
                sm.RunStatus = (int)JobStatus.已启用;
                //更新model
                new ScheduleManage().UpdateScheduleStatus(sm);
                scheduler = await GetSchedulerAsync();
                //resumejob 恢复
                await scheduler.ResumeJob(new JobKey(jobName, jobGroup));

                var status = new StatusViewModel()
                {
                    Status = 0,
                    Msg = "开启任务计划成功",
                };
                return JsonConvert.SerializeObject(status);
            }
            catch (Exception ex)
            {
                var status = new StatusViewModel()
                {
                    Status = -1,
                    Msg = "开启任务计划失败",
                };
                return JsonConvert.SerializeObject(status);
            }
        }
    }

其他几个文件的细节代码我就不再粘贴,详细代码会推到github上去,接下来写一个控制器看看效果!

第四部:项目运行截图



权利声明:本站所有商品信息、客户评价等信息是初心商城重要的数据资源,未经许可,禁止非法转载使用。 注:本站商品信息均来自初心商城,其真实性、准确性和合法性由初心商城负责。

                  初心源说明:初心商城主要为程序员提供开发基础的代码源以及成熟项目,网站中所有的商品有提供收费版本的, 也有提供免费版本的,按照大家各自不同的需求进行购买。实实在在的让程序员只用专注于自己的业务实现你的小梦想, 如果您对我们的成果表示认同并且觉得对你有所帮助我们愿意接受来自各方面的支持^_^。

                  支持:用手机扫描二维码支付

                  支付宝支持我们 微信支持我们

                  您的支持将被用于:
                  1、持续深入的上传更多更好的源代码
                  2、建立更加完善的技术社区
                  3、完善现在系统出现各种问题
                  4、购买域名和租赁服务器

                  1、交易规则

                  2、发货方式

                  1、自动:在上方保障服务中标有自动发货的商品,拍下后,将会自动收到来自卖家的商品获取(下载)链接

                  2、手动:在上方保障服务中标有手动发货的商品,拍下后,卖家会收到邮件,也可通过QQ或订单中的电话联系对方。

                  3、退款说明

                  1、描述:源码描述(含标题)与实际源码不一致的(例:描述PHP实际为ASP、描述的功能实际缺少、版本不符等)

                  2、演示:有演示站时,与实际源码小于95%一致的(但描述中有"不保证完全一样、有变化的可能性"类似显著声明的除外)

                  3、发货:手动发货源码,在卖家未发货前,已申请退款的

                  4、服务:卖家不提供安装服务或需额外收费的(但描述中有显著声明的除外)

                  5、其它:如质量方面的硬性常规问题等

                  备注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。交易中的商品,卖家无法对描述进行修改!

                  4、注意事项

                  1、客户买完之后未确认收货,将不会收到下载地址和下载码,确认收货之后才能收到下载地址和下载码。

                  2、在未拍下前,双方在QQ上所商定的内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准);

                  3、在商品同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外);

                  4、在没有"无任何正当退款依据"的前提下,写有"一旦售出,概不支持退款"等类似的声明,视为无效声明;

                  5、虽然交易产生纠纷的几率很小,但请尽量保留如聊天记录这样的重要信息,以防产生纠纷时出现问题不明确的情况。

                  5、交易声明

                  1、本站作为直卖平台,依据交易合同(商品描述、交易前商定的内容)来保障交易的安全及买卖双方的权益;

                  2、非平台线上交易的商品,出现任何后果均与本站无关;无论卖家以何理由要求线下交易的,请联系管理举报。

                  初心Logo

                  初心商城| 初心系列| 初心博客| 版本历史| 系统反馈

                  © 2016-2019 山西米立信息技术有限公司 保留所有权利 京ICP备16055626号
                  违法和不良信息举报电话:186-2950-9347,本网站所列数据,除特殊说明,所有数据均出自我工作室
                  本网站兼容所有主流浏览器,不支持手机自适应

                  返回顶部小火箭