I have the following query in my project which is using Microsoft.EntityFrameworkCore 7.0.2:
await _context.Actions
.Where(a => a.DateCreated < DateTime.Today && a.ActionType == (int)ActionTypes.ScoredAction && !a.DateCompleted.HasValue)
.ExecuteUpdateAsync(b => b
.SetProperty(x => x.DateCompleted, x => DateTime.Today)
.SetProperty(x => x.ActionResultType, x => LeadScoringConstants.SystemClosed));
But when I try to build, it's saying that IQueryable<ActionEntity> doesn't contain a definition for ExecuteUpdateAsync. Am I missing something here as the documentation says it was added to EF Core 7
ExecuteUpdateAsync is part of the RelationalQueryableExtensions, do not forget to install corresponding nuget (i.e. Microsoft.EntityFrameworkCore.Relational).
Related
Using Entity Framework Core 2.2 I have the following query:
IQueryable<User> users = _context.Users.AsNoTracking();
User user = await users
.Include(x => x.UserSkills)
.ThenInclude(x => x.Skill)
.FirstOrDefaultAsync(x => x.Id == 1);
var userSkills = user.UserSkills.ToList();
IQueryable<Lesson> lessons = _context.Lessons.AsNoTracking();
var test = lessons
.Where(x => x.IsEnabled)
.Where(x => x.LessonSkills.All(y => userSkills.Any(z => y.SkillId == z.SkillId)))
.ToList();
I am looking to get User Skills contains all Lesson Skills.
When I run this query I get the following error:
Exception thrown: 'System.InvalidOperationException' in System.Private.CoreLib.dll:
'Error generated for warning 'Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning:
The LINQ expression 'where ([y].SkillId == [z].SkillId)' could not be translated and will be evaluated locally.'.
How to change the query to solve this problem?
Update
I need to extend this query with an extra option (y.SkillLevelId <= z.SkillLevelId):
var test = lessons
.Where(x => x.IsEnabled)
.Where(x => x.LessonSkills.All(y => userSkills.Any(z =>
y.SkillId == z.SkillId
&&
y.SkillLevelId <= z.SkillLevelId)))
.ToList();
userSkills is in-memory collection, and from my experience with EF6 and EF Core so far I can say that the only reliable translatable construct with in-memory collections is Enumerable.Contains method on primitive type in-memory collection.
So the following solves the problem is question.
First (should be outside the query expression tree):
var userSkillIds = user.UserSkills.Select(x => x.SkillId);
Then instead of
.Where(x => x.LessonSkills.All(y => userSkills.Any(z => y.SkillId == z.SkillId)))
use the equivalent (but translatable):
.Where(x => x.LessonSkills.All(y => userSkillIds.Contains(y.SkillId)))
Update: If you can't use Contains, the options you have until EF Core starts supporting it are (1) EntityFrameworkCore.MemoryJoin package (I personally haven't tested it, but the idea is interesting), (2) manually building Or based predicate with Expression class (hard and works for small memory collections) and (3) replace the memory collection with real IQueryable<>, for instance
var userSkills = users
.Where(x => x.Id == 1)
.SelectMany(x => x.UserSkills);
and use the original query.
I am trying to search records in Nest, my conditions are, expiration_date can be null or it can be within some date(ex. 10-20-2018) and effective_date can be some date (09-20-2018).
Below is my query, here I am not able to use || and && operator, either syntax issue, or my approach is wrong, can anyone help me with this?
docs = await _client.SearchAsync<PriceList>(s => s.Index(config.elasticsearchIndex)
.Query(a => a.Bool(c=>c.Should(
d => d.Bool(e => e.MustNot(f=>f.Exists(g => g.Field(h => h.ExpirationDate))))
||
.Query(a => a.DateRange(r => r.Field(field => field.ExpirationDate).GreaterThanOrEquals(forThisRange.fromDate)))
)))
.Query(a => a.DateRange(r => r.Field(field => field.EffectiveDate).LessThanOrEquals(forThisRange.toDate)))
My nest version is 6.4
UPDATED Query:
.Query(a => a.Bool(c=>c.Should(
d => d.Bool(e => e.MustNot(f=>f.Exists(g => g.Field(h => h.ExpirationDate))))
,
d=>d.Bool(e=>e.Must(f=>f.DateRange(r => r.Field(field => field.ExpirationDate).GreaterThanOrEquals(forThisRange.fromDate))))
//i=>i.DateRange
)))
.Query(a => a.DateRange(r => r.Field(field => field.EffectiveDate).LessThanOrEquals(forThisRange.toDate)))
I am not getting any error, but not getting extra record,it is giving correct result + "expiration_date" has less than 10-20-2018,the later should not.
Thanks all for your comments.
I found the solution, replace .Query() with .PostFilter() which resolved the issue. Don't know the exact difference between them, but it worked.
If anybody knows it, please comment it, may be helpful to others.
Visual studio - MVC Core2 using Microsoft ASP.NET Controller
I am trying to filter records based on a user and if its marked for deletion (bool data type)
I am using the && operator and trying to order by dates column, however its not working
Here is my code
var DataContext = _context.Shops_Basket.Include(c => c.products)
.Where(c => c.Username == user && c.IsDeleted == 0)).Orderby dates desc;
Your OrderBy is wrong in the above. Also the error you are getting sounds like a type-name collision to me. Try to start your variables with lower case letter to avoid this:
var dataContext = _context.Shops_Basket
.Include(c => c.products)
.Where(c => c.Username == user
&& !c.IsDeleted)
.OrderByDescending(c => c.dates);
Orderby dates desc is not valid c#. Probably you are confused by SQL. You need to use OrderByDescending:
var dataContext = _context.Shops_Basket.Include(c => c.products)
.Where(c => c.Username == user && c.IsDeleted == 0)
.OrderByDescending(c => c.dates);
Also note, we have naming conventions in C#. Local variables are starting with a lower character. Underscores like Shops_Basket we usualy do not use. Instead the better DbSet name would be ShopsBasket.
I have this TSQL statement which seems simple enough
select qGroup, AVG(score), COUNT(score)
from [Scores]
where [year] = 2014 and charIndex('s', qGroup, 0) <> 1
group by qGroup
However, I just cannot figure out how to express this in LINQ (dot notation)
Here is my failed stab at it
List<qGroupModel> query = context.Scores.Where(p => (p.schoolID == schoolID) && (p.Year == year) && !(p.qGroup.StartsWith("S"))).Select(p => new { p.Average(p2 => p2.Score), p.qGroup }).GroupBy(p => p.qGroup).ToList<qGroupModel>();
The error I get from the above is as follows
'Models.Score' does not contain a definition for 'Average' and no
extension method 'Average' accepting a first argument of type
'Models.Score' could be found (are you missing a using directive or an
assembly reference?)
My LINQ acumen is not so great.. but still.. this seems harder than it should.
Please help
You can try this way :
List<qGroupModel> query =
context.Scores
.Where(p => (p.schoolID == schoolID) && (p.Year == year) && !(p.qGroup.StartsWith("S")))
.GroupBy(p => p.qGroup)
.Select(p => new qGroupModel { p.Average(p2 => p2.Score), p.qGroup })
.ToList();
All
Please help me make include() work in the following case:
ctx.Messages
.Include("Comments.CommentType")
.Include("Comments.Owner")
.Include("Comments.Message")
.Where(m => m.RID == messageId)
.SelectMany(m => m.Comments)
.Where(c => c.CommentType.Id == commentTypeId)
.ToList();
How I should rewrite this query?
P.S. I'm using EF 3.5 (not 4.0)
This is most likely related to an issue with Include and joins. Basically it comes down to this: Includes are only applied at the end of the statement, and due to joining, the type of your query changes from an IQueryable<Message> to an IQueryable<Comment>.
By removing the join, it should correctly include the navigation properties. Try the following:
ctx.Comments
.Include("CommentType")
.Include("Owner")
.Include("Message")
.Where(c => c.Message.RID == messageId && c => c.CommentType.Id == commentTypeId)
.ToList();