Lambda expression as query for API? - c#

Just started looking at the OData support for the WebAPI and for now it seems like there is alot left to do until the "querying-support" becomes truly interesting.. and thats sort of where this idea were born.. would it be possible some how to send a lambda expression as a querystring and then parse that and run it against an IEnumerable and then return the value?
The whole problem is the expression parsing and how to actually execute the parsed expression against the object.. Im quite unsure about how to do such a thing.. any ideas?.. or is there any place where I can read more about this?
Thanks in advance!

What I understood from your interest is to write your own LINQ parser. check this out: Invent your own dynamic LINQ parser
Also have a look at the discussion happening over implementation of Like operator support for OData here.

Related

How to simplify an expression when converting it to a string?

I need to pass an expression from a WinForms client to a WebApi. I have the following expression:
var results = somelist.Select(p => p.Id).ToList<int>();
Expression<Func<MyObj, bool>> myexp = x => results.Contains(x.Id);
I then simply did:
var str = myexp.Body.ToString();
However, in this particular example, the expression body looks like this:
value(MyApp.MyForm+<>c__DisplayClass41_0).results.Contains(x.Id)
Which obviously will not work when translating back the string to an expression server-side.
Is there a way to reduce, compile, whatever the expression in a better way? Or should I use 3rd party solutions like Remote.Linq or Serialize.Linq?
It depends on what you need to do with the expression on the server side.
If you really only need a string representation you might want to implement an ExpressionVisitor. However, this may require quite some effort, depending the kind of expressions you need to support.
In case you want to convert back to a proper expression tree and execute the expression on server side, it's definitely worth the have a look at Remote.Linq.

Regular Expression matching using Lambda Expressions

I am trying to implement a wildcard search Functionlity for (*,?) using LINQ to SQL. As of now, I want to try it using Regular expression as the code we write will be short and easily manageable. Here is what I have
string kw=_keyword.Replace("*",".*").Replace("?",".");
var predicate = PredicateBuilder.True<DAL.RequestAttribute>();
Regex reg=new Regex("^"+kw+"$");
predicate=predicate &&(reg.IsMatch(ra=>ra.AttributeValue));
So, here it gives a compilation error as "Cannot convert lambda expression to type 'string' because it is not a delegate type"
Though some workarounds if I make it compile and run, I get this runtime Error
"Method 'Boolean IsMatch(System.String)' has no supported translation to SQL."
So, I have two Questions here
1. Am I thinking in right lanes to implement my wildcard using Regular Expressions? if not, which is more efficient way to do this?
2. How to resolve this error .
Thanks
You could mimic SQL's LIKE operator by using SqlMethods.Like: https://msdn.microsoft.com/en-us/library/system.data.linq.sqlclient.sqlmethods.like%28v=vs.110%29.aspx.
Just be sure to use the appropriate wildcards/tokens: https://msdn.microsoft.com/en-us/library/ms179859.aspx.
Update:
You cannot use regular expressions with simple SQL. Since you are essentially building a SQL statement via LINQ, the same rule applies. Though, it's still not quite clear where you are tapping into LINQ with the sample code you've provided.
I would typically expect to see something like the following:
var results =
from Something in SomeLinqContext
where SqlMethods.Like(Something.Value, kw);
After some research I found an answer to my question. Thanks to Ventaur for the Suggestion. the solution is on similar lines but just a bit different. PFB the code for it
string kw=_keyword.Replace("*","%").Replace("?","_");
var predicate = PredicateBuilder.True<DAL.RequestAttribute>();
predicate = (ra => SqlMethods.Like(ra.AttributeValue, kw) && <Any other boolean conditions>
Therefore it boils down to how to make an expression out of SQLMethods.like method using our predicate builder class.

Return filtered String[] from String[] using Linq

Sorry if this has been answered - I have read at least 20 questions that answer an almost identical question but they're all with slightly different circumstances or I can't get them to work.
That's also despite the fact what I want is far more simple! :(
All I want to do is return all the elements of a string array that start with "ABC".
So {"ABC_1", "ABC_2", "ABC_3", "123_1", "ABC_4"}
Will return {"ABC_1", "ABC_2", "ABC_3", "ABC_4"}
Using Linq with Lambda Expressions:
So the logic would be similar to the following:
FilteredArray = StringArray.Where(String.StartsWith("ABC"));
Everytime I try something similar to the above it returns no values.
Thank you in advanced for your help and apologies in advanced for not being able to solve this independently.
P.S If you know of a link that would provide me with a good tutorial on Linq with Lambda Expressions that would be greatly appreciated.
If you want to make an array from an array, you need to use ToArray. You also need to get your LINQ syntax right:
// This assumes that FilteredArray is declared as String[]
FilteredArray = StringArray.Where(str => str.StartsWith("ABC")).ToArray();
Note that Where is not all-caps because identifiers in C# are case-sensitive. Also note the use of the lambda syntax inside the Where method.
I'm not actually sure the original example would compile? Your missing the lambda syntax. This will work correctly. Basically you need to specify the input parameter for the where clause (each of the strings in the array) this is x. Then you do you're string startswith check on that.
var filtered = StringArray.Where(x => x.StartsWith("ABC"));
You need to use the correct syntax in your lambda expression like this
var FilteredArray = StringArray.Where(x => x.StartsWith("ABC")).ToArray();
If you want to learn about Linq expressions then here is a very good solution available for you 101 Linq Samples

Equivalent of Substring as a RegularExpression

Ok, I need a general regular expression that will give me the x characters from a string starting at position y like the string's substring function:
input_str.Substring(y,x)
But as a C# regular expression.
Example:
1234567890 Substring(5,3) 678
I know you are thinking why not just use the Substring function? The short answer is because this goes as a data for an existing function and in this context it would be inelegant to create a whole separate data parsing mechanism. We'd like to get this working without changing the code.
I feel like this is really obvious--but I'm pretty inexperienced with regular expressions. Thanks in advance for any help.
.{y}(.{x}).* should do it, I think, then just pull out the capture group.

Does LINQ have any built-in search which supports search-machine-like searching?

If I have a List<string> and want to do a standard search through it, I can use a LINQ statement like this:
(from t in tasks
where searchTerms.All(term => t.ToUpper().Contains(term.ToUpper()))
select t).ToList();
But if I want to support standard search-engine-like syntax to handle phrases such as:
contract
contract customer
jim customer
"Jim Smith" customer
then I need to start rolling my own custom search method. In addition as Jon Skeet mentioned here, you have to be careful with comparing with ToUpper() with different culture settings, and if you are in a web environment, you have many issues with encoding and searching-for-encoded-characters issues, etc.
Is there not a .NET or LINQ solution which handles search-machine-like searches, e.g. instead of Contains() something like ConstainsSearchTerms()?
If you are using LINQ2SQL, you can use the SqlMethods.Like methods to generate a LIKE like used in SQL.
Else on LINQ2Objects, just use regex.
Regarding ToUpper. This is problematic, the better solution is to use string case folding, but unfortunately .NET only supports the simple model :(
It's not LINQ, but you may want to look into Lucene.NET. It actually is a search engine, and a pretty good one, too.

Categories