#c# #linq #linq-to-objects
#c# #linq #linq-to-objects
Вопрос:
Я использую запрос linq для получения списка объектов, содержащих переменную string:
string str = FilterAllSource;
if (!string.IsNullOrEmpty(str))
{
ss = ss.Where(it => (it.SourceCode.ToUpper()
.Contains(str.ToUpper())
|| it.SourceName.ToUpper()
.Contains(str.ToUpper())));
}
if (top > 0)
ss = ss.Take(top);
return ss.ToList();
когда FilterAllsource содержит amp; (например, m amp; m), он выдает исключение
Unterminated string literal at position 38 in '(ResourceId eq 3) and (substringof('M '.
я предполагаю, что amp; вмешивается в какой-то внутренний процесс конкатенации. Есть ли способ избежать этого, не удаляя amp; из строки запроса?
EDIT1: ss — это список объектов List, где SourceCode и Sourcename являются строками
Комментарии:
1. Это Linq-To-Sql? Что это за провайдер?
2. Пожалуйста, покажите короткую, но полную программу, которая демонстрирует проблему.
3. По крайней мере, тип исключения, который, по вашим словам, вы получаете, мог бы помочь.
4. Я бы посоветовал вам найти строку-нарушитель и написать простую программу типа:
s = "offending text"; string f = "m amp; m"; bool b = s.ToUpper().Contains(f.ToUpper());
Если это выдает ошибку, значит, вы сузили круг поиска. Если ошибка не отображается, значит, проблема в чем-то другом.5. amp; — это escape-код в XML, вы где-нибудь анализируете XML или XAML?
Ответ №1:
У меня это работает…
class Program
{
static void Main(string[] args)
{
Program p = new Program();
List<Test> list = p.GetList();
}
public List<Test> GetList()
{
List<Test> ss = new List<Test>();
ss.Add(new Test("m amp; mm amp; mm amp; mm amp; mm amp; mm amp; mm amp; m", "m amp; mm amp; mm amp; mm amp; mm amp; mm amp; mm amp; m"));
string str = "m amp; m";
if (!string.IsNullOrEmpty(str))
{
ss = ss.Where(it => (it.SourceCode.ToUpper().Contains(str.ToUpper()) || it.SourceName.ToUpper().Contains(str.ToUpper()))).ToList();
}
//if (top > 0)
//{
// ss = ss.Take(top);
//}
return ss.ToList();
}
}
public class Test
{
public Test(string sourceCode, string sourceName)
{
this.SourceCode = sourceCode;
}
public string SourceCode
{
get;
set;
}
public string SourceName
{
get;
set;
}
}
Ответ №2:
Я не смог воспроизвести это, я предполагаю, что это происходит до этого кода. Не могли бы вы материализовать ss перед фильтрацией, например, таким образом, чтобы проверить, изолирован ли образец кода?
var itemsToFilter = ss.ToList();
string str = FilterAllSource;
if (!string.IsNullOrEmpty(str))
{
itemsToFilter = itemsToFilter.Where(it => (it.SourceCode.ToUpper()
.Contains(str.ToUpper())
|| it.SourceName.ToUpper()
.Contains(str.ToUpper())));
}
if (top > 0)
itemsToFilter = itemsToFilter.Take(top);
return itemsToFilter.ToList();
Я пробовал это с linq to objects, сработало нормально:
class Program
{
static void Main(string[] args)
{
var ss = new List<Dummy> { new Dummy
{
SourceCode = "m amp; m",
SourceName = "blabla"
}}.AsEnumerable();
string str = "m amp; m";
if (!string.IsNullOrEmpty(str))
{
ss = ss.Where(it => (it.SourceCode.ToUpper()
.Contains(str.ToUpper())
|| it.SourceName.ToUpper()
.Contains(str.ToUpper()))).ToArray();
}
var top = 2;
if (top > 0)
ss = ss.Take(top).ToArray();
Console.WriteLine(ss.Count());
}
}
public class Dummy
{
public string SourceCode { get; set; }
public string SourceName { get; set; }
}
Также пробовал с linq to sql, не тот же код, но должен вызвать ту же проблему (если была проблема):
class Program
{
static void Main(string[] args)
{
string str = "amp;";
using (var context = new DataClasses1DataContext())
{
var clients = context.Clients.Where(x => x.Code.Contains(str.ToUpper()));
clients = clients.Take(5);
Console.WriteLine(clients.Count());
}
}
}