How to reconcile first and last record in LINQ - c#

I have a table in my SQL database that tracks an employee's in time and out time. A typical record would look like this
Id Device DateTime EmployeeId
-------------------------------------------------------------------------
1 InReader 2013/05/05 08:00:00 1
2 InReader 2013/05/05 08:00:05 1
3 InReader 2013/05/05 08:01:00 2
4 InReader 2013/05/05 08:02:00 3
5 InReader 2013/05/05 08:03:00 4
6 OutReader 2013/05/05 17:00:00 1
7 OutReader 2013/05/05 17:05:05 2
8 OutReader 2013/05/05 17:05:10 2
9 OutReader 2013/05/05 17:10:00 3
10 OutReader 2013/05/05 17:30:00 4
Id is just an auto increment column
Device is the device that they tapped their staff card on, to clock in/or out
DateTime is the time that they tapped their staff card
I would like to know, at the end of the day, when I'm generating a report, how can I reconcile their in-time with out-time, such that the output may look like this:
Employee Id In time Out time
-----------------------------------------------------------------------
1 2013/05/05 08:00:00 2013/05/05 17:00:00
2 2013/05/05 08:01:00 2013/05/05 17:05:10
3 2013/05/05 08:02:00 2013/05/05 17:10:00
4 2013/05/05 08:03:00 2013/05/05 17:30:00
Caveats:
- Note that Employee 1 has 2 records for "InReader", I would want to take the earlier record
- Employee 2 has 2 records for "OutReader", I would want to take only his latest record
How do I reconcile the IN and OUT records using LINQ? (or TSQL if it's not possible in LINQ)

I made you this query, and tested in LinqPad. I'll give you the full code so you can try it yourself.
The query itself:
tracks.GroupBy(x => x.EmployeeId)
.Select(x => new
{
EmployeeId = x.Key,
InTime = x.FirstOrDefault(y => y.Device.Equals("InReader")).DateTime,
OutTime = x.LastOrDefault(y => y.Device.Equals("OutReader")).DateTime
})
The full code sample:
void Main()
{
var tracks = new[]
{
new Track{Id = 1, Device = "InReader", DateTime = new DateTime(2013,5,5,8,0,0), EmployeeId = 1},
new Track{Id = 2, Device = "InReader", DateTime = new DateTime(2013,5,5,8,0,5), EmployeeId = 1},
new Track{Id = 3, Device = "InReader", DateTime = new DateTime(2013,5,5,8,1,0), EmployeeId = 2},
new Track{Id = 4, Device = "InReader", DateTime = new DateTime(2013,5,5,8,2,0), EmployeeId = 3},
new Track{Id = 5, Device = "InReader", DateTime = new DateTime(2013,5,5,8,3,0), EmployeeId = 4},
new Track{Id = 6, Device = "OutReader", DateTime = new DateTime(2013,5,5,17,0,0), EmployeeId = 1},
new Track{Id = 7, Device = "OutReader", DateTime = new DateTime(2013,5,5,17,5,5), EmployeeId = 2},
new Track{Id = 8, Device = "OutReader", DateTime = new DateTime(2013,5,5,17,5,10), EmployeeId = 2},
new Track{Id = 9, Device = "OutReader", DateTime = new DateTime(2013,5,5,17,10,0), EmployeeId = 3},
new Track{Id = 10, Device = "OutReader", DateTime = new DateTime(2013,5,5,17,30,0), EmployeeId = 4},
};
// the Query
tracks
.GroupBy(x => x.EmployeeId)
.Select(x => new
{
EmployeeId = x.Key,
InTime = x.FirstOrDefault(y => y.Device.Equals("InReader")).DateTime,
OutTime = x.LastOrDefault(y => y.Device.Equals("OutReader")).DateTime
})
}
public class Track
{
public int Id { get; set; }
public string Device { get; set; }
public DateTime DateTime { get; set; }
public int EmployeeId { get; set; }
}

Use Min, Max aggregate to returns the smallest or largest element in the sequence and use GroupBy for ordering.
var result=YourTableRowCollection.GroupBy(x=>x.EmployeeId)
.Select(x=>new { EmployeeId=x.Key,
InTime=x.Min(t=>DateTime.Parse(t.InTime)).ToString(),
OutTime=x.Max(t=>DateTime.Parse(t.OutTime)).ToString()});

var x = from current in context.Employess
let firstRecord = current.Where(c=> c.Track.Device == "InReader").OrderBy(c => c.DateTime).First()
let lastRecord = current.Where(c=> c.Track.Device == "OutReader").OrderBy(c => c.DateTime).Last()
select{
// do something
}
Something like that above should do the trick.

var result = table.Where(e => e.Device == "InReader")
.GroupBy(e => e.EmployeeId)
.Select(g => g.OrderBy(d => d.DateTime).First())
.Join(
table.Where(e => e.Device == "OutReader")
.GroupBy(e => e.EmployeeId)
.Select(g => g.OrderByDescending(d => d.DateTime).First()),
t => t.EmployeeId, t => t.EmployeeId,(t, i) => new { Id = t.EmployeeId, In = t.DateTime, Out = i.DateTime });

I suppose that you know your employee's ID (or may be you are going through a list) and the date at which you're generating your report, so first thing you need to do is to get your employee's in and out times of the day with sth. like this:
//first second of the day
DateTime firstSecondOfTheDay = dateToCheck.Subtract(dateToCheck.TimeOfDay);
//last second of the day
TimeSpan endOfDay = new TimeSpan(23, 59, 59);
DateTime lastSecondOfTheDay = firstSecondOfTheDay.Add(endOfDay);
var employeeDayInOut = from emp in context.Employess
where (emp.DateTime >= firstSecondOfTheDay) &
(emp.DateTime <= lastSecondOfTheDay) &
(emp.EmployeeId == idToCheck)
select emp;
You could also easily rewrite this query in order to obtain all employees times of the day, and filter by EmployeeId lately (it depends on what is better for your case).
And after that you can obtain easily from your employee's in and out times of the day the date you need for your report like this:
employeeDayInOut.Max(emp => emp.DateTime);
employeeDayInOut.Min(emp => emp.DateTime);

Related

How to ensure that there are 4 values added for each id

I'm playing with "weeks". I'm retrieving data from a DB in a way like this:
My object in c# looks like this:
public class DemoObj
{
public decimal Amount { get; set; }
public int Month { get; set; }
public int Week { get; set; }
}
I'm grouping data as I wrote on the right of the image, and it works fine and on the end it looks like this:
Month 6
Week 2
Month 8
Week 2
Month 8
Week 3
But I would like to achieve next:
Check if there are no all 4 weeks in one month for example for month with value 8, lets add missing weeks even if that will be empty object, filling week value would be enought so at the end value would look like this:
Month 8
Week 1
Month 8
Week 2
Month 8
Week 3
Month 8
Week 4
So, check if there are not all 4 weeks for value 8, if not, than lets add missing ones..
Here is my current code:
var query = await _context.product
.AsNoTracking()
.Where(x => (x.PaymentDate != null && x.PaymentDate > DateTime.UtcNow.AddMonths(-4))).ToListAsync();
var groupedData = query.GroupBy(x => CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(x.PaymentDate ?? DateTime.UtcNow, CalendarWeekRule.FirstDay, DayOfWeek.Monday))
.Select(product => new productsChartDTO
{
Week = GetWeekNumberOfMonth(product.FirstOrDefault().PaymentDate.Value),
Amount = product.Sum(x => x.Amount),
Month = product.FirstOrDefault().PaymentDate.Value.Month
});
So only for returned months, if there are not all 4 weeks (Values with 1,2,3,4) lets find which one are missing and lets add them something like that.
Any kind of help would be awesome
Thanks
You could group by month and then create a productsChartDTO[4] with an entry for each week:
var groupedData = query.GroupBy(x => (x.PaymentDate ?? DateTime.UtcNow).Month)
.Select(month =>
{
var weeks = Enumerable.Range(1, 4).Select(x => new productsChartDTO() { Month = month.Key, Week = x, Amount = 0 }).ToArray();
foreach (var date in month)
{
int week = GetWeekNumberOfMonth(date.PaymentDate ?? DateTime.UtcNow);
weeks[week - 1].Amount += date.Amount;
}
return weeks;
})
.SelectMany(x => x);
There might be some cleaner way to do it but this works.
static void Main(string[] args)
{
var groupedData = new List<DemoObj>
{
new DemoObj { Amount = 11, Month = 1, Week = 1 },
new DemoObj { Amount = 133, Month = 1, Week = 2 },
new DemoObj { Amount = 323, Month = 1, Week = 3 },
// Needs to add week 4
new DemoObj { Amount = 2342, Month = 2, Week = 1 },
// Needst to add week 2
new DemoObj { Amount = 23433, Month = 2, Week = 3 }
// Needs to add etc..
};
var fullData = AddMissingValues(groupedData);
}
private static IEnumerable<DemoObj> AddMissingValues(IEnumerable<DemoObj> valuesFromDb)
{
var results = valuesFromDb.ToList();
var possibleMonths = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
var possibleWeeks = new[] { 1, 2, 3, 4 };
foreach (var possibleMonth in possibleMonths)
{
foreach (var possibleWeek in possibleWeeks)
{
if (results.Any(x => x.Month == possibleMonth && x.Week == possibleWeek) == false)
{
results.Add(new DemoObj { Month = possibleMonth, Week = possibleWeek });
}
}
}
return results.OrderBy(x => x.Month).ThenBy(x => x.Week);
}
public class DemoObj
{
public decimal Amount { get; set; }
public int Month { get; set; }
public int Week { get; set; }
}

Linq to select objects with unique Id and greatest date?

I have a list of objects that look like this:
public class A
{
public int Id {get; set;}
public DateTime Date {get;set;}
public int TypeId {get; set;}
public int Version {get; set;}
}
My data looks like this:
Id Date TypeId Version
1 10/3/18 1 1
2 10/3/18 1 2
3 10/4/18 1 1
4 10/4/18 2 1
How can I make a linq query to return these 2 in a list where it gets the item with the greatest date where the version # is 1 and also uses the TypeId to return more items?
Id Date TypeId Version
3 10/4/18 1 1
4 10/4/18 2 1
This is what I have tried but my code only returns one item because of my FirstOrDefault function.
var q = from n in A.All.Where(x => x.Version == 1)
group n by n.TypeId into g
select g.OrderByDescending(t => t.Date).FirstOrDefault();
You need to group by typeId and then in each group order elements by date. Then you can pick first element in each group. Try this code:
var input = new[]
{
new A {Id = 1, Date = new DateTime(2018, 10, 3), TypeId = 1, Version = 1},
new A {Id = 2, Date = new DateTime(2018, 10, 3), TypeId = 1, Version = 2},
new A {Id = 3, Date = new DateTime(2018, 10, 4), TypeId = 1, Version = 1},
new A {Id = 4, Date = new DateTime(2018, 10, 4), TypeId = 2, Version = 1},
};
var result = input.Where(a => a.Version == 1)
.GroupBy(a => a.TypeId)
.Select(g => g.OrderByDescending(x => x.Date).First())
.ToArray();

Select values with max date for each ID [duplicate]

This question already has answers here:
How do I get the MAX row with a GROUP BY in LINQ query?
(7 answers)
Closed 5 years ago.
This is the table "history"
id value date
1 1 01/01/2017 20:20:20
1 2 02/01/2017 20:20:20
1 3 03/01/2017 20:20:20
2 5 01/01/2017 20:20:20
2 6 02/01/2017 20:20:20
How with linq select max values for each id
context.History
.GroupBy(x => x.id) ??
.SelectOnlyWithMax(z => z.date) ??
In result only two objects
id value date
1 3 03/01/2017 20:20:20
2 6 02/01/2017 20:20:20
If you want the entire row with the highest date for each Id, you can use the following code (written with LinqPad). If you just want the Id, you can use #BurnsBA's answer, as it will be slightly more efficient.
void Main()
{
var data = new List<Record>
{
new Record(){Id=1, Value=1, Date=new DateTime(2017,1,1)},
new Record(){Id=1, Value=2, Date=new DateTime(2017,2,1)},
new Record(){Id=1, Value=3, Date=new DateTime(2017,3,1)},
new Record(){Id=2, Value=5, Date=new DateTime(2017,1,1)},
new Record(){Id=2, Value=6, Date=new DateTime(2017,2,1)},
};
var query = data.GroupBy(d => d.Id)
.SelectMany(g => g.OrderByDescending(d => d.Date)
.Take(1));
query.Dump();
}
public class Record
{
public int Id { get; set; }
public int Value { get; set; }
public DateTime Date { get; set; }
}
Results:
First it groups by Id, then sorts the items within the group by Date in descending order, and returns the first one, SelectMany then flattens the list.
public class History
{
public int id { get; set; }
public int value { get; set; }
public DateTime date { get; set; }
}
// setup:
var values = new List<History>();
values.Add(new History() { id = 1, value = 1, date = DateTime.Parse("01/01/2017 20:20:20") });
values.Add(new History() { id = 1, value = 2, date = DateTime.Parse("02/01/2017 20:20:20") });
values.Add(new History() { id = 1, value = 3, date = DateTime.Parse("03/01/2017 20:20:20") });
values.Add(new History() { id = 2, value = 5, date = DateTime.Parse("01/01/2017 20:20:20") });
values.Add(new History() { id = 2, value = 6, date = DateTime.Parse("02/01/2017 20:20:20") });
// result :
values.GroupBy(
x => x.id,
y => y.date,
// Below, dates will be enumerable
(id, dates) => new { id = id, date = dates.Max() }
)
// returns enumerable collection of anonymous type:
{
{ id = 1, date = [3/1/2017 8:20:20 PM] },
{ id = 2, date = [2/1/2017 8:20:20 PM] }
}
I suggest MoreLINQ's MaxBy function, that is:
context.History.GroupBy( x => x.id ).Select( x => x.MaxBy( y => y.date) )

Looking for a more elegant LINQ solution

I am trying to figure out an efficient way to retrieve the data I am after. I need to get a list of all of the most recent children by ParentId coupled with all parent entries that do NOT have children. I have created a visual guide to illustrate what the response should be.
The query needs to remain as IQueryable until ALL sorting and paging is completed.
Last and LastOrDefault are not supported by LINQ to Entities (as stated by the error messages I have received while using them).
Using First or FirstOrDefault will return the error "This method or operation is not implemented"
Original Data:
-------------------------------
- Id - ParentId - CreatedDate -
-------------------------------
- 1 - - 07/01/2013 -
- 2 - - 07/01/2013 -
- 3 - - 07/01/2013 -
- 4 - 1 - 07/02/2013 -
- 5 - 2 - 07/03/2013 -
- 6 - 2 - 07/04/2013 -
- 7 - 1 - 07/05/2013 -
-------------------------------
Data returned by query
-------------------------------
- Id - ParentId - CreatedDate -
-------------------------------
- 3 - - 07/01/2013 -
- 6 - 2 - 07/04/2013 -
- 7 - 1 - 07/05/2013 -
-------------------------------
Currently, my LINQ query looks like this:
// Retrieves parent records with NO children.
var q1 = myTable
.Where(x => x.ParentId == null)
.Except(myTable
.Where(x => myTable
.Any(c => (c.ParentId == x.Id))));
// Retrieves most recent child records for each parentId
var q2 =
(from a in myTable
join b in
(myTable.Where(a => a.ParentId != null)
.GroupBy(a => a.ParentId)
.Select(b => new { ParentId = b.Key, CreatedDate = b.Max(t => t.CreatedDate) }))
on a.ParentId equals b.ParentId
where a.CreatedDate == b.CreatedDate
select a);
q1 = q1.Union(q2);
The back-end is using Npgsql2 with PostgreSQL. I am looking for a more elegant solution for this query. I am very new to LINQ and would like to optimize this.
Sorting code (sloppy, but jTable returns these strings):
if (string.IsNullOrEmpty(sorting) || sorting.Equals("Name ASC")) {
q1 = q1.OrderBy(p => p.Customer.Name);
} else if (sorting.Equals("Name DESC")) {
q1 = q1.OrderByDescending(p => p.Customer.Name);
} else if (sorting.Equals("Date ASC")) {
q1 = q1.OrderBy(p => p.CreatedDate);
} else if (sorting.Equals("Date DESC")) {
q1 = q1.OrderByDescending(p => p.CreatedDate);
}
Paging code:
var result = pageSize > 0
? q1.Skip(startIndex).Take(pageSize).ToList()
: q1.ToList();
Use grouping:
Mock data:
public class Entry {
public int Id { get; set; }
public int? ParentId { get; set; }
public DateTime Date { get; set; }
};
var list = new List<Entry> {
new Entry{ Id = 1, ParentId = null, Date = new DateTime(2013, 7, 1) },
new Entry{ Id = 2, ParentId = null, Date = new DateTime(2013, 7, 1) },
new Entry{ Id = 3, ParentId = null, Date = new DateTime(2013, 7, 1) },
new Entry{ Id = 4, ParentId = 1, Date = new DateTime(2013, 7, 2) },
new Entry{ Id = 5, ParentId = 2, Date = new DateTime(2013, 7, 3) },
new Entry{ Id = 6, ParentId = 2, Date = new DateTime(2013, 7, 4) },
new Entry{ Id = 7, ParentId = 1, Date = new DateTime(2013, 7, 5) }
};
Query:
var query = from l in list
group l by l.ParentId into g
select new {
Items = g.OrderBy(x => x.Date).Last()
};
var res = query.OrderBy(x => x.Items.Id).Select(x => x.Items).ToList();
LinqPad result:
Id ParentId Date
3 null 01.07.2013 0:00:00
6 2 04.07.2013 0:00:00
7 1 05.07.2013 0:00:00
I can propose a different query, still in two phases
var firstQuery = myTable.Select(p => new { p.ID, ParentID = p.ParentID ?? p.ID, p.CreatedDate })
.GroupBy( p => p.ParentID).Select( q => new
{
el = q.OrderByDescending( k => k.CreatedDate).Take(1)
}).SelectMany(t => t.el);
var result = dc.TabellaId_ParentId.Where(p => test.Select(q => q.ID).Contains(p.ID));

How to re-write this inner join subquery from SQL to Lambda

SELECT ulcch.ID, ulcch.UserLoginHistoryID, ulcch.StatusID,
ulcch.ClientModuleID, ulcch.DeviceState, ulcch.UpdatedAt, ulcch.CreatedAt
FROM UserLoginClientConnectionHistory AS ulcch INNER JOIN
(SELECT MAX(CreatedAt) AS maxCreatedAt
FROM UserLoginClientConnectionHistory AS ulcch1
GROUP BY UserLoginHistoryID) AS m ON m.maxCreatedAt = ulcch.CreatedAt
There can be many updates of 'device state' per day audited into this login table. This query returns the last unique one for each day.
I would like this re-written as a Lambda statement. This is how far I got, I don't know if i'm on the right track, and my Max() is throwing a type error, probably because the group by is making another list or something...
Hope you can work it out from my object examples.... :S
userLogin.UserLoginClientConnectionHistories.Where(x => x.CreatedAt ==
userLoginClientConnectionHistoryRepository.GetAll(
GenericStatus.Active).GroupBy(y => y.UserLoginHistoryID).Max(y => y.CreatedAt));
I think this does what you want:
var result = userLogin.UserLoginClientConnectionHistories
.GroupBy(y => new { Id = y.UserLoginHistoryID, Day = y.CreatedAt.Date })
.Select(x => new
{
Id = x.Key.Id,
Day = x.Key.Day,
MostRecent = x.Max(y => y.CreatedAt)
});
Here is a testbed for it:
public class Program
{
class LoginEntry
{
public int UserLoginHistoryID { get; set; }
public DateTime CreatedAt { get; set; }
}
class UserLogin
{
public List<LoginEntry> UserLoginClientConnectionHistories = new List<LoginEntry>();
}
public static void Main(string[] args)
{
UserLogin userLogin = new UserLogin();
userLogin.UserLoginClientConnectionHistories = new List<LoginEntry> {
new LoginEntry {UserLoginHistoryID = 1, CreatedAt = new DateTime(2009, 1, 1, 3, 0 ,0)},
new LoginEntry {UserLoginHistoryID = 1, CreatedAt = new DateTime(2009, 1, 1, 15, 0 ,0)},
new LoginEntry {UserLoginHistoryID = 1, CreatedAt = new DateTime(2009, 1, 3, 11, 0 ,0)},
new LoginEntry {UserLoginHistoryID = 1, CreatedAt = new DateTime(2009, 1, 1, 10, 0 ,0)},
new LoginEntry {UserLoginHistoryID = 2, CreatedAt = new DateTime(2009, 1, 3, 4, 0 ,0)},
new LoginEntry {UserLoginHistoryID = 2, CreatedAt = new DateTime(2009, 1, 3, 5, 0 ,0)},
};
var result = userLogin.UserLoginClientConnectionHistories
.GroupBy(y => new { Id = y.UserLoginHistoryID, Day = y.CreatedAt.Date })
.Select(x => new
{
Id = x.Key.Id,
Day = x.Key.Day,
MostRecent = x.Max(y => y.CreatedAt)
});
foreach (var item in result)
{
Console.WriteLine("User {0}, day {1}, most recent {2}",
item.Id,
item.Day,
item.MostRecent);
}
}
}
Output:
User 1, day 01-01-2009 00:00:00, most recent 01-01-2009 15:00:00
User 1, day 03-01-2009 00:00:00, most recent 03-01-2009 11:00:00
User 2, day 03-01-2009 00:00:00, most recent 03-01-2009 05:00:00
Here is the inner join portion as a lambda. I assumed CreatedAt was a dateTime.
UserLoginClientConnectionHistory
.GroupBy (ulcch1 =>
new
{
Name = ulcch1.Name
})
.Select (g =>
new
{
maxCreatedAt = (DateTime?)(g.Max (p => p.CreatedAt))
})
I think you want to group by CreatedAt rather than UserLoginHistoryID:
var q = userLogin.UserLoginClientConnectionHistories
.GroupBy(h => h.CreatedAt)
.OrderByDescending(g => g.Key) // Sort by CreatedAt
.First()
.Select(h => new { h.Id, h.UserLoginHistoryID, ... });
This will return the set of UserLoginClientConnectionHistory entries that share the most recent CreatedAt value.
Thanks for all your help guys, i've voted you all up, but you wouldn't believe it but a few hours later I searched for a program to convert SQL to LINQ, and to my surprise found one called "Linqer". Sounds crazy and didn't expect to get far, but it worked perfectly.. definitely worth checking out that app if anyone else gets stuck in the same boat...
Check the mammoth query it returned! After analysing it, don't think it's got extra bloat? Anyone have any optimisation tips or spot any unnecessary code?
moduleDeviceStates = from ulh in user.UserLoginHistories
join ulcch in userLogin.UserLoginClientConnectionHistories on new { ID = ulh.ID } equals new { ID = ulcch.UserLoginHistoryID }
join cm in clientModuleRepository.GetAll(GenericStatus.Active) on new { ClientModuleID = ulcch.ClientModuleID } equals new { ClientModuleID = cm.ID }
join mo in moduleRepository.GetAll(GenericStatus.Active) on new { ModuleID = cm.ModuleID } equals new { ModuleID = mo.ID }
join m in
(
(from ulcch1 in userLogin.UserLoginClientConnectionHistories
group ulcch1 by new
{
ulcch1.UserLoginHistoryID
} into g
select new
{
maxCreatedAt = g.Max(p => p.CreatedAt)
})) on new { maxCreatedAt = ulcch.CreatedAt } equals new { maxCreatedAt = m.maxCreatedAt }
select new ModuleDeviceState()
{
ModuleID = mo.ID,
Name = mo.Name,
DeviceState = (State.DeviceState)ulcch.DeviceState,
CreatedAt = ulcch.CreatedAt
};
Cheers for your help dahlbyk, but I did want to group on UserLoginHistoryID, I had my query confirmed in SQL before delving into a lambda equivalent :) thanks.
#Mark Thanks for taking the time to reply, yes I do what the [last] entries per user (userloginhistory.. which in turn contains a userID) for each day, and exporting my sql into the linq query did produce what I wanted (which can be seen in the query result below; this is what I want. The reason you see double entries for each day is because there are also attached ClientModule's.. so I really want all client module, per login entry per day - so hard to get a programming requirement across over a discussion forum argh!) Perhaps yours does exactly the same thing (it appears to if I am reading your output correctly) just a lot more streamlined.
See I didn't know too much about the anon casting you've done there with GroupBy and Select, but now I see it, it makes sense. I might give yours a go. Hopefully I can give it a tweak to include distinct ClientModule's per day too. So anyway.. here is the query result from my SQL, and effectively what I got through my own lambda:
ID UserLoginHistoryID StatusID ClientModuleID DeviceState UpdatedAt CreatedAt
277 62 1 1 4 NULL 2009-10-31 13:28:59.003
278 62 1 16 4 NULL 2009-10-31 13:28:59.003
331 65 1 1 4 NULL 2009-10-31 17:13:28.333
332 65 1 16 4 NULL 2009-10-31 17:13:28.333
Update Mark: Hi again, well after a couple of tweaks on your query, I could produce the same object graph in .NET between both lambda statements. This is the one I will use now, derived from yours as it's more streamlined and easier to understand than the auto-gen'd one and I will award you the points :)
I added a few more entries to the Group By as I need that for my new ModuleDeviceState class.
moduleDeviceStates = userLogin.UserLoginClientConnectionHistories
.GroupBy(y => new { Id = y.UserLoginHistoryID,
CreatedAt = y.CreatedAt.Date,
ModuleID = y.ClientModule.ModuleID,
ModuleName = y.ClientModule.Module.Name,
DeviceState = y.DeviceState })
.Select(x => new ModuleDeviceState()
{
ModuleID = x.Key.ModuleID,
Name = x.Key.ModuleName,
DeviceState = (State.DeviceState)x.Key.DeviceState,
CreatedAt = x.Max(y => y.CreatedAt)
});

Categories