Поиск подстановочных файлов XML [дубликат]

TL; DR: Попробуйте использовать Html.Partial вместо Renderpage


Я получал Object reference not set to an instance of an object, когда пытался сделать вид в представлении, отправив ему модель, например это:

@{
    MyEntity M = new MyEntity();
}
@RenderPage("_MyOtherView.cshtml", M); // error in _MyOtherView, the Model was Null

Отладка показала, что модель была Null внутри MyOtherView. Пока я не сменил его на:

@{
    MyEntity M = new MyEntity();
}
@Html.Partial("_MyOtherView.cshtml", M);

И это сработало.

Кроме того, причина, по которой я не имел Html.Partial для начала, заключалась в том, что Visual Studio иногда выдает ошибки, (f9), если он находится внутри другого построенного цикла foreach, хотя это не ошибка:

@inherits System.Web.Mvc.WebViewPage
@{
    ViewBag.Title = "Entity Index";
    List<MyEntity> MyEntities = new List<MyEntity>();
    MyEntities.Add(new MyEntity());
    MyEntities.Add(new MyEntity());
    MyEntities.Add(new MyEntity());
}
<div>
    @{
        foreach(var M in MyEntities)
        {
            // Squiggly lines below. Hovering says: cannot convert method group 'partial' to non-delegate type Object, did you intend to envoke the Method?
            @Html.Partial("MyOtherView.cshtml");
        }
    }
</div>

Но я смог запустить приложение без проблем с этим " ошибка". Я смог избавиться от ошибки, изменив структуру цикла foreach, чтобы выглядеть так:

@foreach(var M in MyEntities){
    ...
}

Хотя я чувствую, что это потому, что Visual Studio неправильно интерпретировала амперсанды и скобки .

32
задан PlayKid 24 June 2009 в 20:18
поделиться

12 ответов

Я бы использовал регулярные выражения, так как вы не всегда можете использовать Linq для SQL.

Как этот пример Linq to Objects

List<string> list = new List<string>();
list.Add("This is a sentence.");
list.Add("This is another one.");
list.Add("C# is fun.");
list.Add("Linq is also fun.");

System.Text.RegularExpressions.Regex regEx = new System.Text.RegularExpressions.Regex("This");

var qry = list
    .Where<string>(item => regEx.IsMatch(item))
    .ToList<string>();

// Print results
foreach (var item in qry)
{
    Console.WriteLine(item);
}
31
ответ дан David Basarab 26 August 2018 в 12:04
поделиться
  • 1
    Бит долго наматывался - он мог просто использовать SqlMethods.Like – user 24 June 2009 в 20:29
  • 2
    Вы всегда считаете, что вызываете базу данных SQL. Что делать, если вы запрашиваете список, который был создан в памяти? – David Basarab 24 June 2009 в 20:33
  • 3
    Его вопрос помечен SQL – user 25 June 2009 в 17:40
  • 4
    Предоставление общего решения для конкретной проблемы НЕ ПЛОХО. – Dementic 26 March 2012 в 13:56

не уверен, если вы говорите LinqToSql или просто linq ... но вы можете использовать регулярные выражения следующим образом:

.Where(dto => System.Text.RegularExpressions.Regex.IsMatch(dto.CustomerName, @"Ad"));
1
ответ дан bytebender 26 August 2018 в 12:04
поделиться

Для Entity Framework Core 2.0 существует LIKE оператор (, объявленный в августе 2017 года ):

var query = from e in _context.Employees
                    where EF.Functions.Like(e.Title, "%developer%")
                    select e;
3
ответ дан Dmitry Pavlov 26 August 2018 в 12:04
поделиться

Вы говорите LINQ с объектами или LINQ to SQL?

Для LINQ для объектов вам придется прибегать к регулярным выражениям , которые я думаю.

0
ответ дан fretje 26 August 2018 в 12:04
поделиться
var result = (from x in db.Members
              where x.IDNumber.Contains(idnumber)
              && x.InstitutionIdentifier == institution.Identifier
              select x).ToList();
return result;

Будет работать как для Linq to SQL, так и для Linq в памяти.

3
ответ дан Gerhard 26 August 2018 в 12:04
поделиться

добавьте System.Data.Linq.SqlClient в ваш список использования или импорта, затем попробуйте:

var results= from x in data
             where SqlMethods.Like(x.SearchField, “%something%like%this%”)
             select x;
14
ответ дан Joe Davis 26 August 2018 в 12:04
поделиться

В .Net-коде, включая LINQ to Objects, я использую реализацию функции IsSqlLikeMatch из потока . Использование Regex для создания подобной функции SQL. .

Пример использования

bool ret = message.IsSqlLikeMatch(pattern);

Более подробно в моем сообщении «похожие» шаблоны SQL для сравнения в .Net

1
ответ дан Michael Freidgeim 26 August 2018 в 12:04
поделиться

Я знаю, что это и старая тема, но вот мое очень простое решение:

string s=Regex.Escape("pattern - escaped for sanity").Replace("%", ".*").Replace("_", ".?");
user => Regex.IsMatch(user.FullName, s, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);

В этом коде я использую общие escape-символы для языка SQL. Если вы хотите использовать say * и ?, escaped string будет содержать \* и \? соответственно, обязательно включите символ обратной косой черты в инструкции (f6) , Конечно, если вы хотите дать своему пользователю возможность искать RexEx, просто не избегайте строки шаблона.

Поиск в учебнике Regex для других опций.

Я считаю, что обычно % будет соответствовать хотя бы одному символу , а RegEx .* будет соответствовать ноль или более символов. Таким образом, в действительности подстановочный символ % больше похож на .+ (жадный), а не на .* (ленивый).

Надеюсь, это поможет.

2
ответ дан nurchi 26 August 2018 в 12:04
поделиться
.Where( column LIKE "Pattern")
2
ответ дан Rony 26 August 2018 в 12:04
поделиться

Глядя на вопрос

Что делать, если я хочу что-то вроде% Test, если% it work%, как это сделать?

then I Я ожидаю что-то из

LIKE '%Test if%it work%'

, что означает, что строка должна содержать «Test if» и «it work» в этом порядке.

Это не сработает:

context.SomeTable.Where(s => s.Name.Contains("Test if%it work")).ToList();

И если я использую:

context.SomeTable.Where(s => s.Name.Contains("Test if") && s.Name.Contains("it work")).ToList();

, тогда я найду все записи, содержащие как «Test if», так и «it work», , но не специально в этом порядке .

Таким образом, с помощью Содержит , это невозможно. Но с IndexOf это.

IndexOf найдет строку поиска и вернет ее позицию в строке. Позволяет найти слова в правильном порядке.

- Обновление -

С моим первоначальным ответом моя цель не заключалась в предоставлении общего решения, а скорее в качестве примера другого подхода, который не зависит от sql. Поэтому верно, что исходный пример отвечает только на вопрос. Но поскольку ответ может быть более полезным, если он является общим, я написал расширение IQuerable, которое позволяет добавить подобный оператор в запрос так же просто, как и оператор where. Расширение работает как для Linq, так и для Linq-Sql.

Здесь будут найдены все записи с «Test if» и «it work» в этом порядке.

context.SomeTable.Like("test if%it work", "Name").ToList();

listOfString.Like("test if%it work").ToList();

Расширение , позволяет любое количество подстановочных знаков:

/// <summary>
/// Allow to search the string with wildcards.
/// </summary>
/// <typeparam name="T">String or an object with a string member.</typeparam>
/// <param name="q">Original query</param>
/// <param name="searchstring">The searchstring</param>
/// <param name="memberName">The name of the field or null if not a field.</param>
/// <returns>Query filtered by 'LIKE'.</returns>
public static IQueryable<T> Like<T>(this IQueryable<T> q, string searchstring, string memberName = null)
{
    // %a%b%c% --> IndexOf(a) > -1 && IndexOf(b) > IndexOf(a) && IndexOf(c) > IndexOf(b)

    var eParam = Expression.Parameter(typeof(T), "e");

    MethodInfo methodInfo;

    // Linq (C#) is case sensitive, but sql isn't. Use StringComparison ignorecase for Linq.
    // Sql however doesn't know StringComparison, so try to determine the provider.
    var isLinq = (q.Provider.GetType().IsGenericType && q.Provider.GetType().GetGenericTypeDefinition() == typeof(EnumerableQuery<>));
    if (isLinq)
        methodInfo = typeof(string).GetMethod("IndexOf", new[] { typeof(string), typeof(StringComparison) });
    else
        methodInfo = typeof(string).GetMethod("IndexOf", new[] { typeof(string) });

    Expression expr;
    if (string.IsNullOrEmpty(memberName))
        expr = eParam;
    else
        expr = Expression.Property(eParam, memberName);

    // Split the searchstring by the wildcard symbol:
    var likeParts = searchstring.Split(new char[] { '%' }, StringSplitOptions.RemoveEmptyEntries);

    for (int i = 0; i < likeParts.Length; i++)
    {
        MethodCallExpression e;
        if (isLinq)
            e = Expression.Call(expr, methodInfo, new Expression[] { Expression.Constant(likeParts[i], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) });
        else
            e = Expression.Call(expr, methodInfo, Expression.Constant(likeParts[i], typeof(string)));

        if (i == 0)
        {
            // e.IndexOf("likePart") > -1
            q = q.Where(Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(e, Expression.Constant(-1, typeof(int))), eParam));
        }
        else
        {
            // e.IndexOf("likePart_previous")
            MethodCallExpression ePrevious;
            if (isLinq)
                ePrevious = Expression.Call(expr, methodInfo, new Expression[] { Expression.Constant(likeParts[i - 1], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) });
            else
                ePrevious = Expression.Call(expr, methodInfo, Expression.Constant(likeParts[i - 1], typeof(string)));

            // e.IndexOf("likePart_previous") < e.IndexOf("likePart")
            q = q.Where(Expression.Lambda<Func<T, bool>>(Expression.LessThan(ePrevious, e), eParam));
        }
    }
    return q;
}

Поскольку для этого не требуется SqlMethods, я предполагаю, что вы можете использовать его для любой базы данных, например MySql или Postgresql. Но я не знаю точно. Я проверил это с Sql-сервером, используя Entity Framework 6. Вышеприведенный оператор генерирует следующий код на сервере Sql.

SELECT [Extent1].* FROM SomeTable AS [Extent1]
WHERE ((( CAST(CHARINDEX(N'test if', [Extent1].[Name]) AS int)) - 1) > -1)
AND ((( CAST(CHARINDEX(N'test if', [Extent1].[Name]) AS int)) - 1) < 
     (( CAST(CHARINDEX(N'it work', [Extent1].[Name]) AS int)) - 1))

Что касается производительности, кажется, есть некоторые дискуссии о том, что «лучше»: LIKE или CHARINDEX. И из того, что я читал, CHARINDEX кажется любимым.

3
ответ дан Ruard van Elburg 26 August 2018 в 12:04
поделиться
  • 1
    В вашем ответе не содержится ответа на общий вопрос о том, как реализовать поиск подстановочных знаков в LINQ, он просто отвечает на конкретный пример и не будет работать для каких-либо других обстоятельств. Таким образом, он не дает полезного ответа на вопрос. – Frosty840 1 March 2017 в 15:44
  • 2
    @ Frosty840 Я обновил ответ. – Ruard van Elburg 2 March 2017 в 03:25
  • 3
    На самом деле я искал SQL-ответ, так как мне не нравится писать дополнительный общий код, который мне никогда не понадобится, так как мы всегда будем использовать SQL Server. К сожалению, пока вы показали, почему содержит не будет работать, вы не показали ничего такого простого. Сравнение, которое я пытаюсь сделать, является одной из строк содержит. Поэтому я надеялся на что-то простое, чтобы добавить к этой строке. Это похоже на SQLMethods.Like придется использовать. – user1161391 20 December 2017 в 18:22

Вы можете использовать SqlMethods.Like () .

Пример использования:

var results =
        from u in users
        where SqlMethods.Like(u.FirstName, "%John%")
        select u;
74
ответ дан Ryan Versaw 26 August 2018 в 12:04
поделиться
  • 1
    очень круто! не знал, что существует ... – bytebender 24 June 2009 в 20:27
  • 2
    Это будет работать только с запросами LinqToSql (как должно быть видно из используемого класса). – Ryan Versaw 24 June 2009 в 20:29
  • 3
    Очень приятно, я не знал, что существует либо +1 – Doctor Jones 24 June 2009 в 20:30
  • 4
    Ничего себе, я никогда не знал, что существует класс SqlMethods. – BFree 24 June 2009 в 20:40

Вы также можете использовать «содержит»

var myresult = db.MyItems.Where(x=>x.MyField.Contains(mysearchstring));
2
ответ дан spadelives 26 August 2018 в 12:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: