Try this:
double NombreECR = context.Developers.ToList( ).Count( number => number.Calcul < 0);
or something like this:
double NombreECR = context.Developers.Count( number => number.DateSoldePr > DateTime.Today);
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Hi,
I have the message
System.InvalidOperationException: The LINQ expression 'DbSet<Developer>()
.Where(d => d.Calcul < 0)' could not be translated. Additional information: Translation of member 'Calcul' on entity type 'Developer' failed. This commonly occurs when the specified member is unmapped. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.<VisitMethodCall>g__CheckTranslated|15_0(ShapedQueryExpression translated, <>c__DisplayClass15_0& )
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.<Execute>b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.Count[TSource](IQueryable`1 source)
In my controller I've definie linq Expression:
public IActionResult MonthlyStats()
{
double NombreECR = context.Developers
.Where(number => number.Calcul < 0)
.Count();
return Ok(NombreECR);
}
In Developer.cs I've defined Developer.Calcul
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public int Calcul
{
get
{
if (DateSoldePr.Year < 2000)
{
return 0;
}
if (DateSoldePr.Year > 2000)
{
return (int)Math.Floor((DateTime.Today - DateSoldePr).TotalDays);
}
else
{
return 0;
}
}
}
do you have any idea how I can solve the problem? I am really stuck in my project
Thanks in advance
Try this:
double NombreECR = context.Developers.ToList( ).Count( number => number.Calcul < 0);
or something like this:
double NombreECR = context.Developers.Count( number => number.DateSoldePr > DateTime.Today);
You are misusing the property and EF cannot translate that. In order to use an expression in LINQ it must be translatable to the underlying provider, EF in your case. For that to happen the property must be get/settable. In your case you're trying to use a calculated property. That is not accessible inside the DB and therefore cannot be used in the LINQ expression that EF has to generate.
If you think about it a second it makes sense. How exactly would EF translate your number.Calcui > 0
to SQL? Ultimately this has to result in a SQL clause that looks like this sometable.Calcui > 0
so the sometable
table would need a Calcui
column. In your case there isn't one so there is no way for the SQL statement to be generated. Calculated properties (nor unmapped properties) cannot be used in LINQ statements backed by EF.
You have a couple of options to fix this. If this is truly a database column then change it from a calculated property and make it settable. EF can then retrieve the value when it makes the DB call. If this is a calculated property then it cannot be used in the LINQ expression. You can remove the DatabaseGenerated
attribute because it means nothing on a calculated property. You don't even need to mark it as unmapped because EF doesn't map properties that don't have a setter (unless you're using field setters but that it is a different discussion).
The only way to use a calculated/unmapped property in EF is to break up the query into 2 pieces. The first piece can run in the DB and is going to be efficient. Then you force the execution of the query (generally a Select
or To...
call). You have now pulled back the data from the DB. You can then use Where
to filter the (now in memory) resultset using any .NET expression.
//Query to run on the DB
var results = context.MyStuff.Where(x => x.SomeDbColumn > 0);
//Force execution
results = results.Select(x => x);
//Now running on the in-memory version so any expression is allowed
results = results.Where(x => x.Calcui > 0);
Just be warned that the DB query needs to filter as much data as possible otherwise you could end up pulling back all your data and then applying a filter on the .NET side which would be expensive.
A final option for your specific case would be to create a view that does the column calculation in SQL. Then update your query to use the view instead of the table. You can then use a get/set property on the model and the Where
expression can be run in the DB again.
Thank you for your answers.
I understand now that calculated columns cannot be used for LINQ expressions but I can use them to display values in my interface.
I have both methods you suggest with the .Calcul column and it still doesn't work.
I don't know why I didn't think of this but the solution below works (great!).
double NombreECR = context.Developers.Count( number => number.DateSoldePr > DateTime.Today);
I would like to add a ratio calculation to my LINQ expression as follows, now I have a format problem
Is the LINQ expression correct?
public IActionResult MonthlyStats()
{
int numberecr = context.Developers.Count();
int calculN = context.Developers.Count(number => number.DateSoldePr > DateTime.Today);
int data = calculN / numberecr;
var stats = context.Developers
.Select(group => new
{
NombreECR = numberecr,
Ratio = data
});
return Ok(stats);
}
I pass the values in the following way
public class Stats
{
public int NombreECR { get; set; }
public int Ratio { get; set; }
public int stats { get; set; }
}
public async Task<Stats> MonthlyStats()
{
var response = await Http.SendAsync(new HttpRequestMessage(HttpMethod.Get, new Uri($"{UriHelper.BaseUri}api/servermethods/MonthlyStats")));
string jsonStr = await response.Content.ReadAsStringAsync();
Stats re = new Stats { stats = int.Parse(jsonStr)};
return re;
// return await response.ReadAsync<Stats>();
}