I'm having trouble writing EF Core expression tree code that would be able to translate to MS SQL Server query utilizing all 3 parameters of its built-in CONVERT function (CONVERT( type[(length)], expression [, style]) - for applying style when converting i.e. datetime to string.
I've managed to write query that translates to CONVERT in SQL, but only passes 2 arguments: type and expression:
Expression.Convert(
Expression.Call(
typeof(Convert),
nameof(Convert.ToString),
Type.EmptyTypes,
Expression.PropertyOrField(parameter, prop.Name)
),
typeof(string)
);
However, if I try using IFormatProvider with Convert.ToString() method (that is, passing the following parameter: Expression.Constant(format, typeof(IFormatProvider)) after Expression.PropertyOrField(parameter, prop.Name), I get exception which states that expression could not be translated to SQL query.
For the testing purposes, format variable is defined as: var format = new CultureInfo("hr-HR");.
Any help would be much appreciated. I'm using EF Core 7.0 and SQL Server.
As of EFCore 7 providing a style parameter to the CONVERT built-in function is not possible.
You can check which built in functions are translated and how here.
You can also see this post about using an IMethodCallTranslator for building an extension yourself, though its an old one(2019). The actual EFCore CONVERT IMethodCallTranslator can be found here.
FYI Instead of CONVERT you can(and probably should) just use DateTime's ToString method. It will work just fine in the final select of your query(top-level projection).
Related
I have a LINQ query where I need to use the CosmosDB ToString method within a query that is built via LINQ in C#. However I have not been able to figure out how to do this. Simply calling ToString() in the C# LINQ expression on the entity value does not work.
I am trying to do a "contains" search on a number value. I can not change the type, and nor can I add a duplicated field that has the number converted to a string.
Essentially what I need is this (in the where clause):
CONTAINS(ToString(root["MyProperty"]), "MySearchValue")
My current LINQ query is this (MyProperty is of type long):
query.Where(x => x.MyProperty.ToString().Contains("MySearchValue"))
But this generates the following SQL:
CONTAINS(root["MyProperty"], "MySearchValue")
Which does not work since MyProperty is a number, so the Contains method always returns false.
So my question is this: How do I modify my LINQ query to wrap the number value in the ToString() method like in my first code sample above? Or is this even possible currently?
There is actually a bugfix for this issue awaiting merge here: https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3385 Does this apply to your specific situation?
This is my code:
var icdCodes = DbContext.MasterIcd.Select(x => x.IcdCode).AsQueryable();
var count = icdCodes.Where(x => !x.Any(char.IsDigit)).Count();
I'm trying to find those IcdCodes which doesn't contain any characters. But using count throws the following error: “Internal .NET Framework Data Provider error 1025.”
As mentioned in Internal .NET Framework Data Provider error 1025 I'm using AsQuerable() but still getting the error. Please help
The AsQueryable() does not solve this other cause of the same error. As also explained in Casting LINQ expression throws "Internal .NET Framework Data Provider error 1025.", the problem is that Where(x => !x.Any(char.IsDigit)) can't be translated to SQL.
The C# code you use treats a string as a char array and calls a function that uses a Unicode lookup table to check if each character is a digit.
The T-SQL variant of this is ISNUMERIC. See How to know if a field is numeric in Linq To SQL:
DbContext.MasterIcd
.Select(x => x.IcdCode)
.Where(i => SqlFunctions.IsNumeric(i) == 1)
.ToList();
Not every Request is translatable into SQL. Splitting a string into an character array and doing array-options on it, might be one of them.
Approach A.
You load all you strings im Memory (replacing AsQueryable with ToList())
And do your Test locally. (your code is OK).
Approach B.
If your IcdCode is of limited length (maximum 9), it could be simpler, just to TryParse it to int or long, disallowing signs if you want. With this Type-Conversion approach there could be also a solution that can be expressed in SQL. (Like if conversion is possible than ...). But it sometimes hard to find out how to express something in C#, that can be converted to SQL, this is what actually is done when executing LINQ to SQL, and it still depends on the type of SQL-Server itself.
I have users who will generate business rules via simple statements that result in true or false
Example: Result > 10 AND Result < 100
I am using Linq.Dynamic to convert these statements I am finding the ParseLambda is taking too long (simple example took 21ms). So I would like to save the Lambda Expression to the database to pull and use later. From my testing I have found the call to ParseLambda is taking the most time, therefore I am wondering if it is possible to serialize this Lambda Expression and persist to a database pulling it when needed. The idea is to have it saved to the database already parsed.
Maybe this is the wrong approach all together. I thought about using CodeDom and scripting but found I would have to create an assembly for every rule, which would pollute the AppDomain, I could have over 1000 rules.
I am open to other options, maybe there is a better library out there.
ParameterExpression P = Expression.Parameter(typeof(InternalEvalData), _ParameterHeading);
LambdaExpression X = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { P }, null, parsedExpression);
result = (bool)d.DynamicInvoke(testData);
I cannot use LinqToSql in my project so I'm implementing something like that. I have an object where I need to compare values :
obj.Where(w=> w.Name == "NAME");
Method Where looks like this :
Where(Expression<Func<T, bool>> expression)
I already know how to get a property name but I nees to ge following information from the expression:
Operator used in expression (==, >=, <=)
Value to which I'm comparing original value
So finally I can build an SQL select query.
EXAMPLE
obj.Where(w=> w.Name == "NAME");
returns
WHERE Name = 'NAME'
Thanks for your help,
B.
You can traverse expression tree, for example using a visitor like in this example. But before developing custom SQL query generator I'd definitely consider using an existing one - the task is really complicated. Entity Framework, for example.
http://geekswithblogs.net/Martinez/archive/2009/06/29/understanding-expression-trees.aspx
By reading this article that expline what are Expression trees and what they are used for I have some question thats the article those not answer me clearly.
A. What is the difference between Data Structure and 'compiled piece of code'.
* I know that data structure is Array,List,.. But this is not the answer I am looking for.
B. Why is it better to use data structure in Entity Framework than 'compiled piece of code' in terms of efficiency.
Answer to both A and B.
The compiled piece of code can not be reverse engineered into something that you can translate to SQL. There are to many details that made the original concepts you want to translate to SQL go away. The expression trees can be analyzed and understood at run time, when the compiled code can not.
Another meta representation of the queries would be possible to use, but the expression trees gives the advantage that existing plumbing in the compiler can be used for a lot of the heavy work.
An Expression is code representing code. It is not an executable piece of code that you can run until you call Compile().
An Expression contains an object graph that describes some code. So the example function:
x => x + 1
Is representing a function that takes 1 parameter, and returns the expression (x + 1). As an object graph, it's something like this:
Expression
AdditionExpression
RightValue
VariableExpression (x)
LeftValue
LiteralExpression (1)
You could parse through the expression and figure out the name of the parts of the expression, or what the literal value is, or what the operation is. Once it is compiled, it is a logical sequence of operations, and all of that metadata is lost.
In terms of Entity Framework, given a sample expression like so:
myObjects.Where(x => x.Id > 10).ToList()
The LINQ to SQL IQueryable provider is inspecting this expression, finding the name of the property Id and then finding the literal value of 10 to convert that into a SQL statement. If this was a function (a compiled unit of code), there is no metadata to inspect, and conversion to SQL would be impossible. It also allows you to deconstruct things into supported and unsupported expressions for efficiency in making sure your SQL query returns the requested data only, instead of a large data set.