2010-07-07 59 views
3

LINQ to SQL是否可以搜索整个数据库(显然只有在.dbml文件中映射的部分)才能匹配字符串?我试图写一个函数,将采取一个“搜索术语”字符串和搜索所有映射的实体,并返回一个List(Of Object),可以包含实体的混合物,即如果我有一个表“Foo”和表“ Bar“并搜索”wibble“,如果在”Foo“中有一行,在”Bar“中包含”wibble“的一行,我想返回包含”Foo“对象和”酒吧“的对象。 这可能吗?使用LINQ to SQL来搜索整个数据库

+0

C#或VB.Net?请注意标签。 – 2010-07-07 08:59:34

+1

有关许多其他示例,请参阅http://msdn.microsoft.com/en-us/vbasic/bb737939.aspx#strcont或http://msdn.microsoft.com/en-us/vbasic/bb688085.aspx。 – 2010-07-07 09:03:59

+1

@Serkan,为什么要重要?他们都应该有相同的方法,我不想限制谁会回答基于语言,因为它真的不打扰我 - 我可以把一个翻译成另一个。 – Ben 2010-07-07 09:04:54

回答

7

LINQ to SQL,一般来说ORMs,甚至SQL对于这样的查询来说都是不匹配的。您正在描述全文搜索,因此您应该使用SQL Server的全文搜索功能。自2000年以来,Full Text Search在所有版本和版本中均可用,包括SQL Server Express。您需要创建一个FTS目录并编写在查询中使用CONTAINS,FREETEXT函数的查询。

为什么你需要这样的功能?除非你特别想让FTS启用你的应用程序,否则这是一种......奇怪的方式来访问你的数据。

+1

我想这样做一次,当数据库结构非常不直观时,我需要查看所有表以找到值的来源。我记得它使用了2个游标。不漂亮。 – 2010-07-07 09:10:06

+0

这是上述权力的要求。我的老板要求我这样做。他想要一个通用搜索,它将根据搜索词返回任何类型的任何对象。 – Ben 2010-07-07 09:13:52

+1

@Ben我假设你试图向他解释那是多么的恶(按@MrFox答案)? – 2010-07-07 09:17:11

3

这可能是'可能的',但大多数数据库都是通过网络或网络访问的,所以它是一个非常昂贵的操作。所以这听起来很糟糕的设计。

另外还有表名和列名的问题,这可能是你最大的问题。这是可能通过反射来获得列名,但我不知道表名:

foreach (PropertyInfo property in typeof(TEntity).GetProperties()) 
    yield return property.Name; 

编辑:@Ben,找你的权利我的错误。

+0

我认为LINQ报道“在服务器上执行此搜索,只返回必要的结果进入记忆“部分对我来说?或者我错了那个? – Ben 2010-07-07 09:17:12

+0

我正在考虑建议类似的东西,包装成助手;但它让我感到非常邪恶,以至于它永远无法“有效地”执行。这可能是将逻辑放在单个存储过程中并自己处理对象创建的情况。 LINQ可以过分地“喋喋不休”,而不会鼓励“到处搜索”:) – 2010-07-07 09:20:21

+0

LINQ to SQL将使用内存中操作来服务一个不能转换为SQL的查询 - 或者更确切地说。如果不使用游标,长语句或未记录的存储过程,甚至无法在SQL中定义所描述的内容。 – 2010-07-07 09:23:50

2

这可以做,但不会很漂亮。有几种可能的解决方案。

1.为每个表编写查询,并在查询方法中执行它们。

var users = context.Users 
    .Where(x => x.FirstName.Contains(txt) || x.LastName.Contains(txt)) 
    .ToList(); 

var products = context.Products 
    .Where(x => x.ProductName.Contains(txt)); 

var result = user.Cast<Object>().Concat(products.Cast<Object>()); 

2.抓取所有(相关)表到存储器中并且使用反射执行搜索。用较少的代码编写付款会带来巨大的性能影响。

3.使用反射为搜索构建表达式树。这可能是最好的解决方案,但它可能很难实现。

4.使用专门用于全文搜索的东西 - 例如集成到SQL Server或Apache Lucene中的全文搜索。

所有的LINQ解决方案(可能)都会要求每个表有一个查询,如果您有很多表,那么这个查询会带来不可忽略的性能影响。这里应该寻找一个解决方案来将这些查询集中到一个查询中。我们使用LINQ to SQL的一个项目使用了一个用于批量查询的库,但我不知道它的名字是什么以及它能做什么,因为我大部分时间都在前端团队工作。

8

问问上司以下几点:

“老板,当你去图书馆找一本关于小部件,你走到第一架并开始阅读每本书,看它是否是相关的,或者你是否使用某种预先编制的索引,图书管理员为你提前帮忙配置?“

如果他说‘嗯,我会使用索引’,那么你需要一个完整的文本索引。

如果他说‘嗯,我将开始一个读每一本书,一个’,那么你需要一个新工作,新的老板,或两者:-)

+0

哈哈,精彩:) – Ben 2010-07-07 11:29:15

+0

@Ben现在你的老板正在阅读图书馆里的每一本书吗? ;) – 2010-07-08 14:02:28

+0

+1,无价... – 2010-07-13 10:47:57

0

可能的,但是从我的角度来看,这是不推荐的。考虑具有的表的100个记录1000K。性能下降,你可以做到这一点的Linq到SQL通过在数据库级别创建一个Sp并通过实体进行调用,它将比您尝试实现的速度快得多=)

0

迟到的答案,但因为我只需要为自己想出一些东西,这里就是了。我编写了以下内容来搜索所有表中的所有列以进行字符串匹配。这与一个数据取证任务有关,这个任务给我发现了一个重约24GB的数据库中出现的字符串匹配的所有情况。在这个尺寸下,你可以想象使用游标或者单线程查询会很慢,而搜索整个数据库将需要很长时间。我编写了下面的CLR存储过程来为我服务器端工作,并在XML中返回结果,同时强制并行化。它非常快速。标准AdventureWorks2017数据库的数据库范围搜索在不到2秒的时间内完成。请享用!

使用范例:

使用服务器上的所有可用的处理器:

EXEC [dbo].[SearchAllTables] @valueSearchTerm = 'john michael' 

限制服务器4个并发线程:

EXEC [dbo].[SearchAllTables] @valueSearchTerm = 'john michael', @maxDegreeOfParallelism = 4 

使用在搜索逻辑运算符条款:

EXEC [dbo].[SearchAllTables] @valueSearchTerm = '(john or michael) and not jack', @tablesSearchTerm = 'not contact' 

限制搜索,表名称和/或列名含有一些搜索术语:

EXEC [dbo].[SearchAllTables] @valueSearchTerm = 'john michael', @tablesSearchTerm = 'person contact', @columnsSearchTerm = 'address name' 

限制搜索结果中的每个表的第一行,其中的术语是发现:

EXEC [dbo].[SearchAllTables] @valueSearchTerm = 'john michael', @getOnlyFirstRowPerTable = 1 

将搜索限制为架构仅自动返回每个表的第一行:

EXEC [dbo].[SearchAllTables] @tablesSearchTerm = 'person contact' 

只返回的搜索查询:

EXEC [dbo].[SearchAllTables] @valueSearchTerm = 'john michael', @tablesSearchTerm = 'person contact', @onlyOutputQueries = 1 

捕获结果纳入临时表和排序:

CREATE TABLE #temp (Result NVARCHAR(MAX)); 
INSERT INTO #temp 
    EXEC [dbo].[SearchAllTables] @valueSearchTerm = 'john'; 
SELECT * FROM #temp ORDER BY Result ASC; 
DROP TABLE #temp; 

https://pastebin.com/RRTrt8ZN