Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.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/2/.net/22.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# String.startswithnotworkingwithtilde(";~";)字符LINQ to SQL?_C#_.net_Linq_Linq To Sql_Linq To Objects - Fatal编程技术网

C# String.startswithnotworkingwithtilde(";~";)字符LINQ to SQL?

C# String.startswithnotworkingwithtilde(";~";)字符LINQ to SQL?,c#,.net,linq,linq-to-sql,linq-to-objects,C#,.net,Linq,Linq To Sql,Linq To Objects,出于某种原因,我使用String.StartsWith()调用IEnumerable.Where()似乎给出了不同的结果,这取决于它是在LINQ to SQL中使用还是在标准LINQ(-to对象)中使用。如果我在同一个调用中添加对ToList()的调用,则会得到不同的结果: var withToList = MyDataContext.MyEntities.ToList().Where(entity => entity.Name.StartsWith("~Test: My Test Str

出于某种原因,我使用String.StartsWith()调用IEnumerable.Where()似乎给出了不同的结果,这取决于它是在LINQ to SQL中使用还是在标准LINQ(-to对象)中使用。如果我在同一个调用中添加对ToList()的调用,则会得到不同的结果:

var withToList = MyDataContext.MyEntities.ToList().Where(entity => entity.Name.StartsWith("~Test: My Test String"));
// withToList.Count() returns 5, which is what I expect.
var direct = MyDataContext.MyEntities.Where(entity => entity.Name.StartsWith("~Test: My Test String"));
// direct.Count() returns 0
我的理解是,与LINQ中的其他一些操作符/方法不同,Where()方法不要求谓词是SQL可翻译的;它在客户端执行,因此可以是任意的.NET代码。(我当然已经抛出了其他非SQL代码并取得了成功)。我甚至得到了一个链接,表明这应该是有效的。怎么回事


编辑:我已经解决了问题;这与我的搜索字符串中是否存在波浪线有关。我更新了标题以反映这一点。

在第一种情况下,实际上
Where
谓词不需要翻译为SQL,因为您首先将整个表放入内存(
ToList
),然后进行过滤

在第二种情况下,
Where
谓词需要可翻译为SQLWHERE子句,因为过滤是在数据库中完成的
string.StartsWith
方法被转换为类似SQL的语句

请记住,通过使用属性。这将有助于您理解它是如何工作的。

此查询将在SQL中执行-因此,您可能会看到一些奇怪之处,具体取决于SQL如何处理“LIKE”。我建议您找出它正在运行的查询,并尝试自己在SQL Management Studio中运行它。在这种情况下,它似乎不正常,尽管它可能是LINQtoSQL中的一个bug;它可能无法正确地逃离事物。(类SQL子句中的~是否表示任何特殊的内容?)


在数据库端执行的任何内容都必须是SQL可翻译的。它不能包含任意的.NET代码—LINQ to SQL只能翻译的代码。否则,组合会被破坏——如果您在之后添加一个连接或一个排序等,那么在SQL中执行某些处理和在客户端执行某些处理将变得非常困难,这两者混合在一起。您可以在SQL中执行一些操作,然后在客户端执行一些操作。请注意,您可以使用
aseneumerable
作为
ToList
的替代方法,以获取要在进程中执行的查询的其余部分。

根据Konamiman的建议,我可以查看正在执行的SQL。这是我得到的(一个模糊不清的例子)

第一个调用执行:

SELECT [t0].[ID], [t0].[Name]
FROM [dbo].[MyEntity] AS [t0]
SELECT COUNT(*) AS [value]
FROM [dbo].[MyEntity] AS [t0]
WHERE [t0].[Name] LIKE @p0 ESCAPE '~'
这是有意义的,因为过滤是在客户端进行的,所以我们需要查询所有行

第二个调用执行:

SELECT [t0].[ID], [t0].[Name]
FROM [dbo].[MyEntity] AS [t0]
SELECT COUNT(*) AS [value]
FROM [dbo].[MyEntity] AS [t0]
WHERE [t0].[Name] LIKE @p0 ESCAPE '~'
因此,乔恩·斯基特走上了正确的道路;我遇到这个问题是因为我的数据/查询条件中碰巧有一个瓷砖。这会导致LINQtoSQL将其标记为转义字符,因此不会在搜索中使用它;这似乎是LINQtoSQL代码中的一个bug

建议的解决方法是使用LINQ的SQLMethods.Like()方法将转义字符从“~”改为其他字符,如下所示:

var direct = MyDataContext.MyEntities.Where(entity => SQLMethods.Like(entity.Name, "~Test: My Test String%", "!");
// direct.Count() now returns 5 as expected
这是可行的,但不幸的是,这是一个只支持LINQ到SQL的解决方案。如果在LINQ to对象版本上尝试,则会出现以下错误:

System.NotSupportedException : Method 'Boolean Like(System.String, System.String, Char)' 
cannot be used on the client; it is only for translation to SQL.
正如Jon Skeet所建议的,使用AsEnumerable()时也会发生同样的情况

我尝试将StartsWith调用包装在一个方法中,并将StartsWith与StringComparisonOption一起使用,但这些方法在LINQ到SQL端不起作用,因为它们不是SQL可翻译的。(因此,我先前关于Where()方法的假设是不正确的)

所以:看起来(直到这个错误被修复)你不能有一个搜索功能,既可以使用波浪形字符,又不知道LINQ的基本味道。(如果有方法,请务必发布)