Ошибка при поиске строки, содержащей

#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());
        }          
    }
}