Reputation: 23
I have a entity that has many columns and has navigation property to another entity in a one to many relationship, now in my navigation property I have a col dateTimeStamp, Now I want to get records including my navi property records but only that which has the latest dateTimeStamp. How can we do it using Lambda expression linq query ?
Entities looks like
public class EntityA {
int entityAId {get;set;}
string desc {get;set;}
...
<ICollection<EntityB>> EntitiesB {get;set;}
}
public class EntityB {
int entityAId {get;set;}
int entityBId {get;set;}
dateTime dateTimeStamp {get;set;}
...
EntityA EntityANavi {get;set;}
}
}
So each EntityA has many EntityB but I want only that EntityB record that has latest dateTime, how can I do that using lambda expression and linq operators?
Data looks like :-
EntityA
EntityAId Desc ...
12 sample1
22 sample2
EntityB
EntityBId EntityAId DateTimeStamp ....
1 12 2020-04-01-10:10:01
1 12 2020-04-01-10:10:21
1 12 2020-04-01-10:11:01
2 22 2020-04-01-11:10:51
2 22 2020-04-01-11:11:01
Result: an Object of
EntityA :{
{entityAId : 12,
desc: sample1
...
EntitiesB :{
EntityB:{ EntityAId:12, EntityBId :1, DateTimeStamp :2020-04-01-10:11:01 .... }
},
{entityAId : 22,
desc: sample2
...
EntitiesB :{
EntityB:{ EntityAId:22, EntityBId :2, DateTimeStamp :2020-04-01-11:11:01 .... }
}
}
}
I tried using EntityA.Include( a => a.EntitiesB.orderByDescending(b => b.DateTimeStamp).First() )
but I keep on getting error
Upvotes: 0
Views: 529
Reputation: 30454
I want to get records including my navi property records but only that which has the latest dateTimeStamp.
var entityAWithItsNewestEntityB = dbContext.EntitiesA.Select(entityA => new
{
// Select the EntityA properties that you plan to use:
Id = entityA.Id,
Name = entityA.Name,
...
NewestEntityB = entityA.EntitiesB
.OrderByDescending(entityB => entityB.DateTimestamp)
.Select(entityB => new
{
// Select only the EntityB properties that you plan to use
Id = entityB.Id,
Name = entityB.Name,
...
// Foreign key not needed, you already know the value:
// EntityeAId = entityB.EntityAId,
})
.FirstOrDefault(),
});
In words: from every EntityA object in the collection of EntityA objects, select one or more properties. Also order all EntityB objects of this EntityA by descending DateTimeStamp, such that the newest EntityB will be first. From this ordered sequence of EntityB objects, select several properties. From the result take only the first one, or null if EntityA has no EntityB objects at all.
Simple comme bonjour!
Upvotes: 1
Reputation: 324
I assume you are using Entity Framework. For EFcore the good news is, it will come in the future and is available in preview 5.0 for efcore: https://github.com/dotnet/efcore/commit/21b9a35db594f7a383e855f922babbe54b3d38c5
As for now in an eager loading scenario, as soon as you .Include you're loading any object you are referring to. You can load the required Entities for EntityB and include EntityA to them. A working solution would be:
List<EntityA> listA = ctx.EntityA.Include(k=>k.EntitiesB).ThenInclude(k=>k.EntityANavi)
.select(k=>k.EntitiesB.OrderByDescending(l=>l.DateTimeStamp).FirstOrDefualt())
.ToList().Where(EntityANavi != null).Select(k=>k.EntityANavi);
Essentially can loading everything and select those objects which are need. After Including EntitiesB, i included EvntityANavi again to make sure the relation is retained. After that just select, "filter" and forget. (.ToList() is to actually load the data and make sure you only have one query running for the datareader, since we keep going on on the query)
Upvotes: 1
Reputation: 81
try :
var query = EntityA.OrderBy(a => a.EntitiesB.Min(b => b.dateTimeStamp.Date))
.ToList()
Upvotes: 0