I have method like below:
public async Task<IEnumerable<DateTime>> GetReportDates(int monthsBack)
{
return await _entities.view
.OrderByDescending(d => d.LastUpdateDate)
.Take(monthsBack)
.Select(d => d.LastUpdateDate.Value)
.Distinct()
.ToListAsync();
}
My problem is that when I run my MVC page it stops on this method. I was waiting for few minutes with no success. There are about 600 rows in that view so it should not be a problem. Any suggestions what could be wrong here?
Related
Given this simple Contract entity and assuming that a customer can have many Contracts with different start dates and statuses.
public class Contract {
[Key]
int ContractId { get; set; }
int CustomerId { get; set; }
string Status { get; set; }
DateTime ContractStartDate { get; set; }
}
I'm trying to write a query to find that latest contract for each customer and then filter out certain statuses. I need to filter the status after finding the latest contract, to ensure I'm getting their current status.
ContractID
CustomerID
ContractStartDate
Status
1
1
2022-01-01
Active
2
1
2022-31-05
Inactive
3
2
2022-01-03
Active
4
2
2022-31-07
Inactive
From the above data set, I would expect to get contracts 2 and 4 in the results. This is why I can't filter on status before grouping, because then the latest inactive row would be eliminated before I group them by customer to find the latest row.
I've tried something like, this:
var latestContracts = Query<Contract>()
.GroupBy(grp => grp.CustomerId)
.Select(s => s.OrderByDescending(s => s.ContractStartDate).First())
.Where(w => w.Status == "Active");
but once I execute the query by calling ToListAsync(), etc. I get an error like this:
'The LINQ expression 'DbSet<Customer>()
.GroupBy(c => c.CustomerId)
.Select(g => g
.AsQueryable()
.OrderByDescending(e => e.
I CC ContractStartDate)
.First())
.Where(e0 => e0.AccountContractTermStatus == "Active")' could not be translated. 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.'
If I remove the Where call, the query works fine and gives the intended newest results. I know that the support for translating LINQ to SQL is still not fully complete, even in EF Core 6, but this seems like something that should be possible. Am I missing something simple or is this just not yet doable via LINQ?
Happy to provide more context, as I've greatly simplified a production query into something I could share publicly.
Try the following emulation of query which EF Core cannot translate. It is almost direct translation what EF Core should do in your case.
var dataQuery = Query<Contract>();
var latestContracts =
from d in dataQuery.Select(d => new { d.CustomerId }).Distinct()
from c in dataQuery
.Where(c => d.CustomerId == c.CustomerId)
.OrderByDescending(c => c.ContractStartDate)
.Take(1)
where c.Status == "Active"
select c;
Or using Method Chain syntax:
var dataQuery = Query<Contract>();
var latestContracts = dataQuery
.Select(d => new { d.CustomerId })
.Distinct()
.SelectMany(d => dataQuery
.Where(c => d.CustomerId == c.CustomerId)
.OrderByDescending(c => c.ContractStartDate)
.Take(1))
.Where(c => c.Status == "Active");
I am currently trying to figure out how to load an angular/fire-collection including all of its subcollections with RxJS.
This is my current approach:
return this.collectionRef.valueChanges().pipe(
flatMap((entities: Entity[]) => entity),
mergeMap((entity: Entity) => this.setSubCollection1(entity)),
mergeMap((entity: Entity) => this.setSubCollection2(entity)),
scan((entities: Entity[], entity: Entity) => entities.filter(a => a.id !== entity.id).concat(entity), [])
);
and to load the documents in their subcollections
private setSubCollection1 = (entity: Entity): Observable<Entity> => {
return this.subCollectionRef.valueChanges(actor).pipe(
map((subEntities1: SubEntity1[]) => {
entity.subEntities1 = subEntities1;
return entity;
})
);
}
It works fine when having a full stream.
But now I wanted to get all of data in one single Promise: I already tried .first().toPromise() but this only gets the first entry, and does not finish if the collection has no entries. Using reduce in the query also does not work, because valueChanges() never finishes.
Am I using the wrong operators? Or any other ideas on how to solve that?
I hope to hear from you.
So I have this query
return await Order
.query()
.with('order_status')
.where('order_status.is_completed_type', true)
I want to only get the orders with order_status.is_completed_type === true
but it seems that doesn't work that way, is there a way to do this?
You can do it by passing query builder config to .with method: https://adonisjs.com/docs/4.1/relationships#_adding_runtime_constraints
So in your case:
return await Order
.query()
.with('order_status', q=> {
q.where('is_completed_type', true)
})
I am not a rxjs expert.
I have a method which actually does a save.
this.saveProducts(this.boxes, 'BOXES')
But there are two other different type of items that needs to use the same method for saving , just the parameter is different.
this.saveProducts(this.containers, 'CONTAINER')
In my component I have few other independent saving is happening and all these should happen one by one.
So my method look like this.
return this.service.edit(materials)
.do((data) => {
this.materials= data;
})
.switchMap(() => this.customerService.addCustomer(this.id, this.customers))
.switchMap(() => this.saveProducts(this.boxes, 'BOXES'))
.switchMap(() => this.saveProducts(this.containers, 'CONTAINER'))
.switchMap(() => this.saveProducts(this.books, 'BOOKS'))
.do(() => {
.......
}
But whats happening is it never calls the second saveProducts method unless I have a return from first one
private saveProducts(products: IProduct[], type:
Type): Observable<any> {
console.log(type);
}
Thanks for anyone who looked at it..
The answer to this issue is to return an empty observable if nothing is there to save.
if (products$.length === 0) {
return Observable.of([]);
}
Thanks guys.. Happy coding..
I have some classes defining entities with relationships
Account
has many Conversations [IEnumerable<Conversation> Conversations]
Conversation
has many Participants [IEnumerable<Account> Participants]
has many Messages [IEnumerable<Message> Messages]
Message
has one Sender [Account Sender]
has one Conversation [Conversation Conversation]
I'm trying to write a LINQ query that returns a list of Conversation ordered by date and including related participants and messages.
public async Task<List<Conversation>> FindAllByAccountIdAsync(Int32 id)
{
return await _Db.Conversations
.Where(c => c.Participants.Any(p => p.AccountId == id))
.Include(c => c.Participants)
.Include(c => c.Messages)
.ToListAsync();
}
This do the work but includes to much data i do not really need.
public async Task<List<Conversation>> FindAllByAccountIdAsync(Int32 id)
{
return await _Db.Conversations
.Where(c => c.Participants.Any(a => a.AccountId == id))
.Include(c => c.Participants.Select(a=> new
{
AccountId = a.AccountId,
Profile = new { FullName = a.Profile.FullName,
Email = a.Profile.Email
}
}))
// Only return the last message in
// Eventually I would not return an array with a single object but just the single object inside associated with the property LastMessageIn
.Include(c => c.Messages.OrderBy(m => m.Date).Select(m=> new
{
Body = m.Body,
SenderId = m.Sender.AccountId
}).Last())
.ToListAsync();
}
This script returns a mile long exception
{"message":"An error has occurred.","exceptionMessage":"The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties........}
My mind resist understanding and learning LINQ I do not know if its just me but as soon requirements exceeds basic querying and projection it break out of my control
Someone have some hints?
I'm not sure if I understand your question, but I believe you want something like this:
public async Task<List<Conversation>> FindAllByAccountIdAsync(Int32 id)
{
return await _Db.Conversations
.Where(c => c.Participants.Any(p => p.AccountId == id))
.Include(c => c.Participants)
.Include(c => c.Messages)
.Select(c => new
{
Participants = c.Participants.Select(a=> new
{
AccountId = a.AccountId,
Profile = new { FullName = a.Profile.FullName,
Email = a.Profile.Email
}
},
//EDIT: using OrderByDescending and FirstOrDefault
Messages = c.Messages.OrderByDescending(m => m.Date).Select(m=> new
{
Body = m.Body,
SenderId = m.Sender.AccountId
}).FirstOrDefault())
//others properties here
}
.ToListAsync();
}
You cannot project on an Include. An include is simply Eager Loading. The output does not change in the C#. Only the amount of data that is originally loaded (ie performance) changes.
It seems you want a projection and not eager loading, which are completely incompatible concepts.
However I cannot understand what exactly what you are trying to achieve.
public async Task<List<Conversation>> FindAllByAccountIdAsync(Int32 id)
{
return await _Db.Conversations
.Where(c => c.Participants.Any(p => p.AccountId == id))
.Include(c => c.Participants.Select(_=>_))
.Include(c => c.Messages.Select(_=>_))
.ToListAsync();
}
Should be enough.