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 неправильно интерпретировала амперсанды и скобки .
Я бы использовал регулярные выражения, так как вы не всегда можете использовать 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);
}
не уверен, если вы говорите LinqToSql или просто linq ... но вы можете использовать регулярные выражения следующим образом:
.Where(dto => System.Text.RegularExpressions.Regex.IsMatch(dto.CustomerName, @"Ad"));
Для Entity Framework Core 2.0
существует LIKE
оператор (, объявленный в августе 2017 года ):
var query = from e in _context.Employees
where EF.Functions.Like(e.Title, "%developer%")
select e;
Вы говорите LINQ с объектами или LINQ to SQL?
Для LINQ для объектов вам придется прибегать к регулярным выражениям , которые я думаю.
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 в памяти.
добавьте System.Data.Linq.SqlClient в ваш список использования или импорта, затем попробуйте:
var results= from x in data
where SqlMethods.Like(x.SearchField, “%something%like%this%”)
select x;
В .Net-коде, включая LINQ to Objects, я использую реализацию функции IsSqlLikeMatch из потока . Использование Regex для создания подобной функции SQL. .
Пример использования
bool ret = message.IsSqlLikeMatch(pattern);
Более подробно в моем сообщении «похожие» шаблоны SQL для сравнения в .Net
Я знаю, что это и старая тема, но вот мое очень простое решение:
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 .*
будет соответствовать ноль или более символов. Таким образом, в действительности подстановочный символ %
больше похож на .+
(жадный), а не на .*
(ленивый).
Надеюсь, это поможет.
Глядя на вопрос
Что делать, если я хочу что-то вроде% Test, если% it work%, как это сделать?
blockquote>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 кажется любимым.
Вы можете использовать SqlMethods.Like () .
Пример использования:
var results =
from u in users
where SqlMethods.Like(u.FirstName, "%John%")
select u;
Вы также можете использовать «содержит»
var myresult = db.MyItems.Where(x=>x.MyField.Contains(mysearchstring));