I have this already
if (options.English != null) query = query
.Where(w => w.English.Contains(options.English));
What I would like to do is to extend this (maybe with another if clause) to make it so that if:
a user enters ^abc then my query would check if the word starts with "abc".
a user abc then it would check if the column contains "abc"
I am using a SQL Server back-end database. Could anyone give me a suggestion as to how I could implement this functionality.
Assuming that you're using Entity Framework, you can use the StartsWith() and EndsWith() methods, to achieve the same results as Contains() except only at the beginning or the end of a string. It will generate the code for you.
Then simply create conditional statements in your code, in order to determine which one of the methods you should use.
Some word of advice:
There might be a bug with EF Core, in which it turns StartsWith("string") into LIKE "string%" which might yield incorrect results with strings, containing wildcard characters such as "_".
So I'd advise you to use plain SQL with EF Core, and given that you're using SQL Server as a DBMS, query like that:
if (searchText.StartsWith("^"))
{
var result = query.FromSql($"SELECT something FROM table WHERE PATINDEX({searchText.Substring(1)}, something) = 1");
}
else
{
var result = query.FromSql($"SELECT * FROM table WHERE PATINDEX({searchText.Substring(1)}, something ) <> 0");
}
With PATINDEX() you will get correct results even if your pattern string contains wildcard characters - escaping potential bugs with relying on StartsWith() and EndsWith() to generate proper SQL code.
But that's only for EF Core, EF 6 works like a charm the way other people answered :)
You can put that choice in a conditional statement:
IQueryable<Whatever> query = ...;
if (searchText.StartsWith("^"))
{
query = query.Where(w => w.English.StartsWith(searchText.Substring(1)));
}
else
{
query = query.Where(w => w.English.Contains(searchText));
}
You can also do the same comparison inline, but that'll generate very ugly SQL, if it even works:
query = query.Where(w =>
searchText.StartsWith("^")
? w.English.StartsWith(searchText.Substring(1))
: w.English.Contains(searchText));
Do note that you generally don't want to search text using SQL, as that results in a pretty poor user experience. Take a look at full-text indexing.
if (options.English != null)
{
bool englishStartsWith = options.English.StartsWith("^");
if(englishStartsWith)
{
query = query.Where(w => w.English.StartsWith(options.English.Substring(1)));
}
else
{
query = query.Where(w => w.English.Contains(options.English));
}
}
I currently have a LINQ statement which works fine with Method Syntax. Am curious to see how would the equivalent query syntax look like. Tried doing multiple iterations but couldn't succeed with query syntax
Currently I have 2 strings - one being a sentence and other being an alphabet. I convert both of them into character for comparison - so I can find the number of occurrences of the character in the full string.
string sentenceToScan = "I Love StackOverflow!!!!";
string characterToScanFor = "e";
var stringToCheckAsCharacterArray = sentenceToScan.ToCharArray();
var characterToCheckFor = Char.Parse(characterToScanFor);
int numberOfOccurenes = stringToCheckAsCharacterArray.Count(n =>
n == characterToCheckFor);
Answer: 2
Count doesn't have a query expression syntax, it can only be appended at the end of a query expression like:
var count = (from t in stringToCheckAsCharacterArray
where t == characterToCheckFor).Count();
Or
var count = (from t in stringToCheckAsCharacterArray
where t == characterToCheckFor
select t).Count();
Personally I like Method expression, also LINQ query expression compiles in Method expressions. Your own code for Count with predicate is more readable IMO.
My LINQ is rusty, but something like:
stringToCheckAsCharacterArray.Where(n => n == characterToCheckFor).Count();
I would like to concatenate a string using lambda to compare that concatenated value against a certain condition.
Invoices = Invoices.Where(f => ((string)f.invoice_prefix + String.Format("{0:0000}", Convert.ToInt32(f.invoice_number))).ToLower().Equals(condition7));
But I get an error message :
The name 'f' does not exist in the current context
Tried several String.Format and String.Concat variants like
Invoices = Invoices.Where(f => (String.Format("{0}{1}",f.invoice_prefix,String.Format("{0:0000}", Convert.ToInt32(f.invoice_number)))).ToLower().Equals(condition7));
but no success... Can somebody help me with the syntax?
Thanks in advance!
Linq to Entities doesn't understand all of the .NET framework methods.
In order to run this as a SQL statement on the database, you need to only use operators that can be converted to SQL. That means you need to re-write your predicate using primitive data types.
So something like this:
string prefixCondition = ...
int invoiceNumberCondition = ...
Invoices.Where( f =>
f.invoice_prefix == prefixCondition
&&
f.invoice_number == invoiceNumberCondition
)
I recommend using LinqPad to test with, as it shows you the generated SQL statement.
I am slowly porting over an app from MySQL to use Linq2Sql - but one query has stumped me a bit.
SELECT * FROM Pages WHERE DomainID = #reportid AND (PageContent REGEXP 'display:[ \t]*none') > 0 ORDER BY URL ASC
Any ideas on how I would write something like this with Linq2SQL? Its the REGEXP bit thats got me stumped?
There is no way built in to LINQ to SQL, but you have a couple of other choices. The first is to load your strings in as in-memory objects which you can apply Regex functions to. I'm not a big fan of this since it looks like you're potentially getting some very big strings to match against.
The second option is to leverage SQL CLR as described here. This effectively lets you create a stored procedure that gets linked to a CLR method that you create. Whenever you call the method in a LINQ to SQL context, it gets converted to a stored procedure call. Then you use a query like this:
var q = from p in context.Pages
where p.DomainId == reportId &&
RegExMatch(p.PageContent, "display\:[ \t]*none")
select p;
Why not use LINQ to return items that match on reportid and that contain 'display:', to minimise the amount of data being returned from the server, and then use regex on client side to filter that list down?
var query = Pages.Where( p => p.DomainId == 1 && p.PageContent.IndexOf("display:") > 0).OrderBy( o => o.URL );
var regex = new Regex(#"display\:[\t]*none");
foreach (var page in query)
{
if( regex.IsMatch(page.PageContent) )
{
// Do whatever...
}
}
This question already has answers here:
How to make LINQ execute a (SQL) LIKE range search
(3 answers)
Closed 2 years ago.
I have a textbox that allows a user to specify a search string, including wild cards, for example:
Joh*
*Johnson
*mit*
*ack*on
Before using LINQ to Entities, I had a stored procedure which took that string as parameter and did:
SELECT * FROM Table WHERE Name LIKE #searchTerm
And then I would just do a String.Replace('*', '%') before passing it in.
Now with LINQ to Entities I am trying to accomplish the same thing. I know there is StartsWith, EndsWith and Contains support, but it won't support it in the way that I need.
I read about "SqlMethods.Like" and tried this:
var people = from t in entities.People
where SqlMethods.Like(t.Name, searchTerm)
select new { t.Name };
However I am getting the following exception:
LINQ to Entities does not recognize the method 'Boolean Like(System.String,
System.String)' method, and this method cannot be translated into a store
expression.
How would I get this same functionality using LINQ to Entities?
http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/6529a35b-6629-44fb-8ea4-3a44d232d6b9/
var people = entities.People.Where("it.Name LIKE #searchTerm", new ObjectParameter("searchTerm", searchTerm));
How to get it to work seamlessly:
in your EDMX model, add:
<Function Name="String_Like" ReturnType="Edm.Boolean">
<Parameter Name="searchingIn" Type="Edm.String" />
<Parameter Name="lookingFor" Type="Edm.String" />
<DefiningExpression>
searchingIn LIKE lookingFor
</DefiningExpression>
</Function>
just after the sections that start:
<edmx:ConceptualModels>
<Schema Namespace="Your.Namespace"...
Then, anywhere in your code, add this extension method:
//prior to EF 6 [System.Data.Objects.DataClasses.EdmFunction("Your.Namespace", "String_Like")]
//With EF 6
[System.Data.Entity.DbFunction("Your.Namespace", "String_Like")]
public static bool Like(this string input, string pattern)
{
/* Turn "off" all regular expression related syntax in
* the pattern string. */
pattern = Regex.Escape(pattern);
/* Replace the SQL LIKE wildcard metacharacters with the
* equivalent regular expression metacharacters. */
pattern = pattern.Replace("%", ".*?").Replace("_", ".");
/* The previous call to Regex.Escape actually turned off
* too many metacharacters, i.e. those which are recognized by
* both the regular expression engine and the SQL LIKE
* statement ([...] and [^...]). Those metacharacters have
* to be manually unescaped here. */
pattern = pattern.Replace(#"\[", "[").Replace(#"\]", "]").Replace(#"\^", "^");
return Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase);
}
And there you have it.
Now you can do:
(from e in Entities
where e.Name like '%dfghj%'
select e)
or
string [] test = {"Sydney", "Melbourne", "adelaide", "ryde"};
test.Where(t=> t.Like("%yd%e%")).Dump();
Well, your choices are:
Use Contains. I know you don't like it, but it could probably be made to work.
Pick a function from SqlFunctions. They're all supported in L2E.
Map your own function.
+1 to #Yury for ESQL.
You can do this:
using System.Data.Entity; // EntityFramework.dll v4.3
var queryResult=db.Accounts.AsQueryable().Where(x => x.Name.Contains(queryKey));
because Linq to Entity can't transform the method Contains() to the SQL, but Linq to SQL can do this. I tried to find a method that can doing a cast, at last, AsQueryable(), also a generic version AsQueryable<T>(). I found I can do this using it this way in my case, but any side effect it has I don't know, maybe it will lose some feature at Entity.
the solution is to use SQLFunctions.PatIndex
var result = from c in items
where SqlFunctions.PatIndex(searchstring.ToLower(), c.fieldtoSearch) > 0
select c;
where 'searchstring' is the pattern to search
'fieldtoSearch' is the field to search
Patindex() supports search using string pattern search. The search is case insensitive.
Now, EF supports "LIKE" usage and you can use all sql wildcards. Check this out.
var people = from t in entities.People
select new { t.Name };
people = people.Where(x => DbFunctions.Like(x.Name, searchTerm));
You can do all these statements with LINQ like this
string _search = "johnson";
// joh* OR joh%
items.Where(i => i.Name.StartsWith(_search, StringComparison.OrdinalIgnoreCase));
// *son OR %son
items.Where(i => i.Name.EndsWith(_search, StringComparison.OrdinalIgnoreCase));
// *hns* OR %hns%
items.Where(i => i.Name.ToLower().Contains(_search));
var people = from t in entities.People
where t.Name.ToLower().Contains(searchTerm.ToLower())
select new { t.Name };
EDIT- I might be mixing syntax. I usually use extension methods; but contains will work.
It is easily achieved by following methods
var people = from t in entities.People
where t.Name.Contains(searchTerm)
select new { t.Name };
Use the following specifications to achieve wildcards
LIKE 'a%' => StartsWith("a")
LIKE '%a' => EndsWith("a")
LIKE '%a%' => Contains("a")
LIKE 'a%b' => StartsWith("a") && EndsWith("b")
LIKE '%a%b%' => StartsWith("a") && Contains("b")
You do not need to use percent sign while filtering. e.g;
if I want to check ItemName does not contain '-' I will do it like this
!Item.ItemName.Contains("-")
In SQL it will convert to NOT LIKE '%-%'
We use Database First and the EntityFramework.
The "Map your own function." approach works for us together with the nuget EntityFramework.CodeFirstStoreFunctions.
1 Step: Create a function in the db like this:
CREATE FUNCTION [dbo].[StringLike]
(
#a nvarchar(4000),
#b nvarchar(4000)
)
RETURNS bit
AS
BEGIN
RETURN
(SELECT CASE
WHEN (SELECT 1 WHERE #a LIKE #b) = 1 THEN 1
ELSE 0
END)
END
2 Step: Install nuget EntityFramework.CodeFirstStoreFunctions
3 Step: Create a method in your code like this (I create mine in the DbContext class):
[DbFunction("CodeFirstDatabaseSchema", "StringLike")]
public static bool Like(string input, string pattern)
{
throw new NotSupportedException("Direct calls are not supported.");
}
4 Step: Initalize EntityFramework.CodeFirstStoreFunctions.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(new FunctionsConvention("dbo", this.GetType()));
}
5 Step: Now you can use this method in your linq query.