Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何编写易于理解(/可维护)的搜索函数?也许是以模块化的方式?_C#_Java - Fatal编程技术网

C# 如何编写易于理解(/可维护)的搜索函数?也许是以模块化的方式?

C# 如何编写易于理解(/可维护)的搜索函数?也许是以模块化的方式?,c#,java,C#,Java,每次我看到一个搜索函数,它背后的代码都是一团糟。几百行,意大利面代码,几乎总是作为一个巨大的方法。一种编程语言(Java/C#/PHP/etc)被用来构造一个大型SQL查询。很多,很多如果其他的 一定有比这更优雅的方法吗?或者这就是使用RMDBS而不是平面数据结构时得到的结果 我愿意更多地了解这个话题,甚至买本书/亚当使用。如果可以,也可以使用ORM,这将使事情变得更容易。 实施细节取决于您的平台和体系结构,但以下是一些示例: 在我当前的项目中,我们使用了mausch提到的查询对象模式的简

每次我看到一个搜索函数,它背后的代码都是一团糟。几百行,意大利面代码,几乎总是作为一个巨大的方法。一种编程语言(Java/C#/PHP/etc)被用来构造一个大型SQL查询。很多,很多如果其他的

一定有比这更优雅的方法吗?或者这就是使用RMDBS而不是平面数据结构时得到的结果

我愿意更多地了解这个话题,甚至买本书/亚当

使用。如果可以,也可以使用ORM,这将使事情变得更容易。 实施细节取决于您的平台和体系结构,但以下是一些示例:


在我当前的项目中,我们使用了mausch提到的查询对象模式的简化版本。在本例中,我们有一个搜索条件对象,它由一个字段和一个值组成,可以将几个这样的对象添加到列表中。我们从一开始就有一个操作符属性,但它从未被使用,所以我们删除了它。是否将标准视为AND或or取决于所使用的搜索方法(我想说的是,在该项目中95%的情况下都是如此)

find方法本身并没有对这些信息做很多处理;它们将调用数据库中存储的进程,并将条件作为参数传递。这些过程中的大多数都是相当直接的,尽管我们有一些确实涉及到一些字符串处理的过程来解压某些字段的critera列表

从调用者的角度来看,代码可能如下所示(控制器类将重复的内容包装为使用可配置实现*实例化搜索对象,并使用搜索条件等填充该对象):

CustomerCollection customers=CustomerController.Find(新的搜索条件(“名称”),“”);
如果需要多个搜索条件,则可以传递集合。在finder函数中,代码将在集合上循环,将当前值映射到SqlCommand对象中的适当参数

这种方法对我们来说效果相当好


*)“可配置实现”意味着我们已经创建了一个架构,当搜索对象被定义为抽象类时,这些抽象类只会定义接口,并包含一些通用的验证前和验证后。实际的搜索代码在单独的Decent类中实现;这使得我们能够快速创建一个“假数据层”,用于模拟一些单元测试的数据库。

您看过Lucene项目()了吗?它的设计正是为了这个目的。其思想是您构建并维护一组易于搜索的索引。生命周期的工作原理如下:

SQL.select("column1", "column2")
   .from("relation")
   .where().valueEquals("column1", "hello")
           .and().valueIsLargerThan("column2", 3)
   .toSQL();
  • 编写一组sql语句,对数据库的所有可搜索区域进行索引
  • 对完整数据库运行它们,以创建数据的初始索引
  • 每次数据更改时,更新这些索引
查询语言简单得多,您的查询变得更有针对性


在hibernate工具套件中有一个名为hibernate search()的伟大项目,如果您使用hibernate作为ORM,它可以为您维护索引。

我已经对这个想法做了一些修改(因为我之前确实必须实现类似的东西)我得出的结论是,有两种方法可以让它既能工作又特别容易维护。但在讨论这些之前,先来看看历史

1.为什么这个问题会存在 大多数搜索功能都基于从数据库中派生的算法和技术。SQL最初是在20世纪70年代早期开发的(),当时的编程是一种完全不同于今天的怪兽,因为每一个字节计数,每一个额外的函数调用都会在出色的性能和破产之间产生差异,代码是由在汇编中思考的人编写的……好吧,你明白了

问题在于,这些技术最初大部分都是在没有改变它们的情况下被带到现代世界的(为什么它们应该被改变,而不是修复一些未被破坏的东西),这意味着旧的范式也在悄然蔓延。还有一些情况下,原始算法由于某种原因被曲解了,你最终得到了你现在拥有的,比如。不过,这里需要强调一下,技术本身并不坏,通常只是遗留范例而已

2.问题的解决办法 我最终使用的解决方案是一个混合了和(已经由mausch链接)的系统。举个例子,如果我要创建一个实用的系统来构建SQL查询,它将如下所示:

SQL.select("column1", "column2")
   .from("relation")
   .where().valueEquals("column1", "hello")
           .and().valueIsLargerThan("column2", 3)
   .toSQL();
这样做的明显缺点是构建器模式有点过于冗长。好处是每个构建步骤(=方法)本质上都很小,例如
.valueIsLargerThan(“a”,x)
可能只是
返回columnName+“>=”+x。这意味着它们很容易进行单元测试,最大的优点之一是它们可以很容易地从外部源(如XML/whatnot)生成,最值得注意的是,创建从SQL查询到Lucene查询的转换器相当容易(Lucene已经实现了自动化,这只是一个示例)

我宁愿使用但真正避免的第二种方法是,当构建器在运行时,它不是顺序安全的(除非您花费大量时间创建元数据帮助器类)。写一个例子比详细说明我的意思更容易,因此:

import static com.org.whatever.SQL.*;

query(select("column1", "column2"),
      from("relation"),
      where(valueEquals("column1", "hello"), 
            valueIsLargerThan("column2", 3)));

我确实认为静态导入是一个缺点,但除此之外,这似乎是我真正想要使用的东西。

这是一个时代的问题!同意。NHibernate的ICriteria API让这一切变得简单(relat