我如何使用LINQ Contains(string )而不是Contains(string)

我有一个很大的问题。

我有一个linq查询来把它看起来像这样:

from xx in table where xx.uid.ToString().Contains(string[]) select xx 

string[]数组的值将是数字(1,45,20,10等)

.Contains的默认值是.Contains(string)

我需要它来做这个,而不是: .Contains(string[])

编辑:一个用户build议写string[]的扩展类。 我想学习如何,但是任何人都愿意把我指向正确的方向?

编辑: uid也是一个数字。 这就是为什么它被转换成一个string。

帮助任何人?

spoulson几乎是正确的,但是你需要首先从string[]创build一个List<string> 。 其实一个List<int>会更好,如果uid也是intList<T>支持Contains() 。 做uid.ToString().Contains(string[])意味着作为一个string的uid包含数组的所有值作为子string? 即使你写了扩展方法,它的感觉也是错误的。

[编辑]

除非你像Mitch Wheat所说的那样把它改写成string[] ,那么你就可以跳过转换步骤。

[EndEdit中]

这里是你想要的,如果你没有做扩展方法(除非你已经有潜在的用户集合作为整数 – 那么就用List<int>()来代替)。 这使用链式方法的语法,我认为是更清洁,并进行转换为int,以确保查询可以用于更多的提供者。

 var uids = arrayofuids.Select(id => int.Parse(id)).ToList(); var selected = table.Where(t => uids.Contains(t.uid)); 

如果您真的想要复制Contains ,但对于数组,这里是扩展方法和示例代码的用法:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ContainsAnyThingy { class Program { static void Main(string[] args) { string testValue = "123345789"; //will print true Console.WriteLine(testValue.ContainsAny("123", "987", "554")); //but so will this also print true Console.WriteLine(testValue.ContainsAny("1", "987", "554")); Console.ReadKey(); } } public static class StringExtensions { public static bool ContainsAny(this string str, params string[] values) { if (!string.IsNullOrEmpty(str) || values.Length > 0) { foreach (string value in values) { if(str.Contains(value)) return true; } } return false; } } } 

尝试以下。

 string input = "someString"; string[] toSearchFor = GetSearchStrings(); var containsAll = toSearchFor.All(x => input.Contains(x)); 

.NET 4.0中的LINQ为您提供了另一种select; .Any()方法;

 string[] values = new[] { "1", "2", "3" }; string data = "some string 1"; bool containsAny = values.Any(data.Contains); 

或者,如果你已经有一个列表中的数据,而且更喜欢其他Linq格式:)

 List<string> uids = new List<string>(){"1", "45", "20", "10"}; List<user> table = GetDataFromSomewhere(); List<user> newTable = table.Where(xx => uids.Contains(xx.uid)).ToList(); 

怎么样:

 from xx in table where stringarray.Contains(xx.uid.ToString()) select xx 

这是写一个扩展方法的一种方法的例子(注意:我不会使用这个非常大的数组;另一个数据结构会更合适…):

 namespace StringExtensionMethods { public static class StringExtension { public static bool Contains(this string[] stringarray, string pat) { bool result = false; foreach (string s in stringarray) { if (s == pat) { result = true; break; } } return result; } } } 

这是一个迟到的答案,但我相信它仍然有用
我创build了NinjaNye.SearchExtension nuget包,可以帮助解决这个问题:

 string[] terms = new[]{"search", "term", "collection"}; var result = context.Table.Search(terms, x => x.Name); 

您也可以search多个string属性

 var result = context.Table.Search(terms, x => x.Name, p.Description); 

或者执行一个返回IQueryable<IRanked<T>>RankedSearch ,它只是包含一个显示search条件出现次数的属性:

 //Perform search and rank results by the most hits var result = context.Table.RankedSearch(terms, x => x.Name, x.Description) .OrderByDescending(r = r.Hits); 

有关GitHub页面的更详细的指南: https : //github.com/ninjanye/SearchExtensions

希望这有助于未来的游客

我相信你也可以做这样的事情。

 from xx in table where (from yy in string[] select yy).Contains(xx.uid.ToString()) select xx 

Linq扩展方法。 将使用任何IEnumerable对象:

  public static bool ContainsAny<T>(this IEnumerable<T> Collection, IEnumerable<T> Values) { return Collection.Any(x=> Values.Contains(x)); } 

用法:

 string[] Array1 = {"1", "2"}; string[] Array2 = {"2", "4"}; bool Array2ItemsInArray1 = List1.ContainsAny(List2); 

那么我是否正确地假设uid是唯一标识符(Guid)? 这只是一个可能的场景的例子,或者你真的想要find一个匹配string数组的GUID?

如果这是真的,你可能想重新考虑这个方法,这似乎是一个非常糟糕的主意。 你可能应该试图把Guid和Guid相匹配

 Guid id = new Guid(uid); var query = from xx in table where xx.uid == id select xx; 

我真的不能想象一个场景,在Guid的内容中使用“contains”来匹配string数组是一个好主意。 一方面,Contains()不能保证Guid中的数字顺序,所以你可能会匹配多个项目。 更不用说比较guid这种方式会比直接做的慢。

你应该反过来写它,检查你的priviliged用户ID列表包含该行的表上的ID:

 string[] search = new string[] { "2", "3" }; var result = from x in xx where search.Contains(x.uid.ToString()) select x; 

LINQ在这里performance得相当好,并将其转换为一个好的SQL语句:

 sp_executesql N'SELECT [t0].[uid] FROM [dbo].[xx] AS [t0] WHERE (CONVERT(NVarChar,[t0].[uid])) IN (@p0, @p1)',N'@p0 nvarchar(1), @p1 nvarchar(1)',@p0=N'2',@p1=N'3' 

它基本上将'search'数组的内容embedded到sql查询中,并在SQL中用'IN'关键字进行过滤。

我设法find一个解决scheme,但不是一个伟大的,因为它需要使用AsEnumerable()这将返回从数据库中的所有结果,幸运的是,我只有1Klogging在表中,所以它不是真正知名的,但在这里。

 var users = from u in (from u in ctx.Users where u.Mod_Status != "D" select u).AsEnumerable() where ar.All(n => u.FullName.IndexOf(n, StringComparison.InvariantCultureIgnoreCase) >= 0) select u; 

我原来的post如下:

你如何做相反的事情? 我想在entity framework中做如下的事情。

 string[] search = new string[] { "John", "Doe" }; var users = from u in ctx.Users from s in search where u.FullName.Contains(s) select u; 

我想要的是find所有的用户,其FullName包含“search”中的所有元素。 我尝试了很多不同的方法,所有这些方法都没有为我工作。

我也试过了

 var users = from u in ctx.Users select u; foreach (string s in search) { users = users.Where(u => u.FullName.Contains(s)); } 

该版本仅查找包含search数组中最后一个元素的那些版本。

我find的最好的解决scheme是继续前进,并在SQL中创build一个Table-Valued函数来产生结果,例如::

 CREATE function [dbo].[getMatches](@textStr nvarchar(50)) returns @MatchTbl table( Fullname nvarchar(50) null, ID nvarchar(50) null ) as begin declare @SearchStr nvarchar(50); set @SearchStr = '%' + @textStr + '%'; insert into @MatchTbl select (LName + ', ' + FName + ' ' + MName) AS FullName, ID = ID from employees where LName like @SearchStr; return; end GO select * from dbo.getMatches('j') 

然后,只需将该函数拖放到您的LINQ.dbmldevise器中,然后像调用其他对象那样调用它。 LINQ甚至知道你存储的函数的列。 我这样叫出来::

 Dim db As New NobleLINQ Dim LNameSearch As String = txt_searchLName.Text Dim hlink As HyperLink For Each ee In db.getMatches(LNameSearch) hlink = New HyperLink With {.Text = ee.Fullname & "<br />", .NavigateUrl = "?ID=" & ee.ID} pnl_results.Controls.Add(hlink) Next 

令人难以置信的简单,并真正利用在应用程序中的SQL和LINQ的力量…当然,您可以生成任何表值的function,你想要的相同的效果!

我相信你真正想要做的是:让我们想象一下,你有两个数据库的情况下,他们有一个共同的产品表你要从表中select“A”的产品,ID与“B”

使用这个方法包含的过于复杂,我们正在做的是一个十字路口,还有一个叫做十字路口的方法

msdn的示例: http : //msdn.microsoft.com/en-us/vcsharp/aa336761.aspx#intersect1

int [] numbers =(0,2,4,5,6,8,9); int [] numbersB =(1,3,5,7,8); var = commonNumbers numbersA.Intersect(numbersB);

我觉得你所需要的是很容易解决的交集

检查这个扩展方法:

 using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace ContainsAnyProgram { class Program { static void Main(string[] args) { const string iphoneAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like..."; var majorAgents = new[] { "iPhone", "Android", "iPad" }; var minorAgents = new[] { "Blackberry", "Windows Phone" }; // true Console.WriteLine(iphoneAgent.ContainsAny(majorAgents)); // false Console.WriteLine(iphoneAgent.ContainsAny(minorAgents)); Console.ReadKey(); } } public static class StringExtensions { /// <summary> /// Replicates Contains but for an array /// </summary> /// <param name="str">The string.</param> /// <param name="values">The values.</param> /// <returns></returns> public static bool ContainsAny(this string str, params string[] values) { if (!string.IsNullOrEmpty(str) && values.Length > 0) return values.Any(str.Contains); return false; } } } 
 from xx in table where xx.uid.Split(',').Contains(string value ) select xx 

尝试:

 var stringInput = "test"; var listOfNames = GetNames(); var result = from names in listOfNames where names.firstName.Trim().ToLower().Contains(stringInput.Trim().ToLower()); select names; 
 string[] stringArray = {1,45,20,10}; from xx in table where stringArray.Contains(xx.uid.ToString()) select xx 
 Dim stringArray() = {"Pink Floyd", "AC/DC"} Dim inSQL = From alb In albums Where stringArray.Contains(alb.Field(Of String)("Artiste").ToString()) Select New With { .Album = alb.Field(Of String)("Album"), .Annee = StrReverse(alb.Field(Of Integer)("Annee").ToString()) }