solr主从复制

最近的开发工作涉及到两个模块“任务”和“日周报”。关系是日周报消费任务,因为用户在写日周报的时候,需要按一定的规则筛选当前用户的任务,作为日周报的一部分提交。整个项目采用类似于Orchard那种平台加插件的架构,“任务”和“日周报”是两个独立的插件。

“任务”已经由一位同事事先写好,周报中筛选任务的规则简单描述如下:

  • 截止日期在周一之前,且未完成的任务(超期或待审核);
  • 截止日期在周一至周日之间的所有任务;
  • 开始日期在周一至周日之间的所有任务;
  • 截止日期在周日之后,且未设置开始日期的所有任务(进行中或待审核)。

看起来貌似挺简单,敲代码的时候却发现下不了手,“任务”的仓储层对“日周报”是不可见的,想要按照规则查询任务列表,我只能调用TaskService,但TaskService中并没有根据上述规则来筛选任务的方法。

怎么办呢?为TaskService添加个实现上述规则的方法,比如GetTasksForWeeklyReport?想了想,貌似不是一个好的思路,因为是“日周报”在消费“任务”模块,任务模块应该是不知道日周报的存在的,直接写一个只针对周报的方法总觉得心里有点不对劲。而且,也不希望以后日周报的需求更改而影响到任务。

再想想,日报中也有自己筛选任务的规则,按照上面那么搞,还需要为日报添加个方法GetTasksForDailyReport。如果其他的业务模块也需要按一定的规则筛选任务列表的话,方法还得继续追加下去。这样势必会造成TaskService的无比臃肿,而且其他的模块的规则已修改,就要同步修改任务模块。如果任务模块单独部署到一台机器上,这种麻烦程度就会更大。

这时候夜壶般的脑袋中闪过一个词:规约。

规约模式可以简单理解为条件判断。就不在此照搬那些费解的概念了,按照现在遇到的问题举例来说,我希望TaskService中有个这样的方法:

GetTasksBySpecification(ISpecification specification);

specification是一个描述任务筛选规则的对象,TaskService可以根据这个对象所描述的规则来找出Task集合。对于周报来说,只需要实现ISpecification接口的具体实例,然后调用TaskService的GetTasksBySpecification方法并传递规约实例,就可以拿到想要的任务列表。对于日报来说,也一样,实现自己的规约类就好。以后再有其他业务模块需要根据自己的规则筛选任务的时候,也只需要实现一个规约类。

这样就可以保证“任务”模块的完整性,而且避免了TaskService无限臃肿的顾虑。

有了思想,就剩下具体实现了。主要参考了大神陈晴阳开发的DDD开发框架Apworks,其中提供了规约模式的.Net实现。

最终类图如下:

ISpecification中定义了规约类需要实现的方法,其中IsSatisfiedBy用来判断一个对象是否满足改规约,GetExpression用来获取表示该规约的表达式树。DailyReportTaskSpecification和WeeklyReportTaskSpecification用来描述筛选规则。有时候查询需要根据两个规约以“and”条件进行查询,所以又有了AndSpecification,用来把两个规约以and条件组合到一起。

周报中任务筛选规则的规约类代码大概是:

public class WeeklyReportTaskSpecification : SpecificationBase<TaskEntity>{
public override Expression<Func<TaskEntity, bool>> GetExpression(){
return task =>.....;
}
}

根据用户Id筛选任务的规约类代码:

public class UserInChargeTaskSpecification : SpecificationBase<TaskEntity>{
#region 私有字段
private readonly long _inchargeUserId;
#endregion #region 构造器
public UserInChargeTaskSpecification(long inChargeUserId){
_inchargeUserId = inChargeUserId;
}
#endregion #region SpecificationBase<TaskEntity> 成员
public override Expression<Func<TaskEntity, bool>> GetExpression(){
return task =>task.UserIncharge!=null && task.UserIncharge == _inchargeUserId;
}
#endregion
}

TaskService实现规约查询的方法:

public IEnumerable<TaskEntity> GetTasksBySpecification(ISpecification<TaskEntity> spec){
return taskRepository.Table.Where(spec.IsSatisfiedBy);
}

周报中通过如下代码实现对TaskService中规约方法的调用:

public IEnumerable<TaskEntity> GetWeeklyTask(long userId, DateTime currentDateTime){
var userInChargeTaskSpecification = new UserInChargeTaskSpecification(userId);
var weeklyReportTaskSpecification = new WeeklyReportTaskSpecification(); return TaskService.GetTasksBySpecification(userInChargeTaskSpecification.And(weeklyReportTaskSpecification));
}

除了需要根据规则筛选任务列表之外,还需要根据当前用户的Id过滤,因为当前用户只关心自己的任务。所以把两个规约类通过And方法连接到一块,组成一个规约,传递给GetTasksBySpecification方法。

试了下效果,五星好评!!!

补充:

往这篇博客中贴代码的时候,TaskService中的GetTasksBySpecification中的实现让我有点不放心。

因为ISpecification的IsSatisfiedBy属性返回的是表达式树Compile之后的委托,我直接传递给linq一个委托,会不会造成全表扫描?不会把整个表的数据加载到内存,然后挨个用委托过滤吧。这个很好验证,查看一下最终执行的sql就可以了。

然后在园子里找到了dudu的这篇文章:Func引起的数据库全表查询

于是GetTasksBySpecification的代码修改如下:

public IEnumerable<TaskEntity> GetTasksBySpecification(ISpecification<TaskEntity> spec){
return taskRepository.Table.Where(spec.GetExpression());
}

solr主从复制的更多相关文章

  1. solr与.net系列课程(七)solr主从复制

    solr与.net系列课程(七)solr主从复制    既然solr是解决大量数据全文索引的方案,由于高并发的问题,我们就要考虑solr的负载均衡了,solr提供非常简单的主从复制的配置方法,那么下面 ...

  2. solr与.net课程(七)solr主从复制

    既然solr是解决大量数据全文索引的方案,因为高并发的问题,我们就要考虑solr的负载均衡了,solr提供很easy的主从复制的配置方法,那么以下我们就来配置一下solr的主从复制 如果我们在192. ...

  3. solr与.net主从复制

    solr主从复制 solr与.net系列课程(七)solr主从复制    既然solr是解决大量数据全文索引的方案,由于高并发的问题,我们就要考虑solr的负载均衡了,solr提供非常简单的主从复制的 ...

  4. solr学习2

    1:solr中的时间问题 solr中显示的时间默认会比我们本机时间少八个小时,因为时区不一样. 在solr的web页面查看会发现时间少八个小时. 但是使用java代码操作的时候是整成的的,所以在这只需 ...

  5. solr6.6初探之主从同步

    1.关于solr索引数据同步 通常情况下,单节点部署的solr应用很难在并发量很大的情况下"久存",那么多节点部署提高Solr应用的负载量和响应时间势在必行. solr索引同步有以 ...

  6. Solr学习总结(七)Solr搜索引擎的整体架构

    经过前面一段时间的努力,终于把我所知道的关于solr 的内容都总结完了.前面讲到了solr 的安装配置,web管理后台的使用,solr 的查询参数和查询语法,还说到了solr的客户端 solrnet  ...

  7. 05 Apache Solr: 管理员界面(Admin UI)

         为了方便管理员和工程师调整Solr的配置和访问在线文档和其他的帮助,Solr提供了一个Web界面去查看Solr的配置详情,运行查询语句和分析文档字段.这个界面在第三篇里面提到过就是管理员界面 ...

  8. Solr主从集群配置简要说明

    关于solr的集群主要分为主从和SolrCloud两种.主从,比较适合以读为主的场景.SolrCloud适合数据量大,时不时会有更新的情形.那么solr的主从配置很简单.在solrconfig.xml ...

  9. Solr搜索引擎入门知识汇总

    1.技术选型,为什么用solr而不用lucene,或者其他检索工具 lucene:需要开发者自己维护索引文件,在多机环境中备份同步索引文件很是麻烦 Lucene本质上是搜索库,不是独立的应用程序.而S ...

随机推荐

  1. Spark大师之路:广播变量(Broadcast)源代码分析

    概述 近期工作上忙死了--广播变量这一块事实上早就看过了,一直没有贴出来. 本文基于Spark 1.0源代码分析,主要探讨广播变量的初始化.创建.读取以及清除. 类关系 BroadcastManage ...

  2. jQuery、Ajax分页

    1.效果预览 2.HTML代码 <div class="row"> <div class="col-lg-12 col-sm-12 col-xs-12 ...

  3. ASP.NET MVC应用程序展示RDLC报表

    原文:ASP.NET MVC应用程序展示RDLC报表 学习ASP.NET MVC这样久,在学习,练习与应用过程中,觉得很多知识与以前的ASP.NET多有区别,但是实现操作起来,细处又有许多相近的地方. ...

  4. Is it always safe to call getClass() within the subclass constructor?(转)

    14down votefavorite   An article on classloading states that the method getClass() should not be cal ...

  5. async和await关键字实现异步编程

    async和await关键字实现异步编程 异步编程   概念 异步编程核心为异步操作,该操作一旦启动将在一段时间内完成.所谓异步,关键是实现了两点:(1)正在执行的此操作,不会阻塞原来的线程(2)一旦 ...

  6. JMeter 怎么保存登录状态

    在Recording Controller中添加一个HTTP Cookie Manager Recording Controller右键-->add-->config element--& ...

  7. C++定义自己的命名空间和头文件

    下面的例子演示如何使用一个简单的演示空间和自己的头文件定义.码如下面: compare.h: namespace compare{ double max(const double* data,int ...

  8. Dos命令将合并两个文本文件的内容

    当生产线的问题,有一个放b.txt的内容被添加到a.txt这需要采取.在考虑这个问题.我的第一感觉是敲代码.阅读b.txt内容,渐进写a.txt.想起昨天在加工处理生产线600M决的方法,我用java ...

  9. C++ Primer第九章课后编程问题

    1. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ3V1Z2xlMjAxMA==/font/5a6L5L2T/fontsize/400/fill/I0J ...

  10. 后台自动启动appium

    首先说明,本人用的exe方式安装的appium. 新建一个.vbs文件,写入以下脚本,记得把D盘换成你自己的盘符. 1.后面taskkill好像没有实际作用..加就加了吧. Set ws = Crea ...