Closed axelheer closed 4 years ago
I've never worked with this LINQ syntax (always prefer extensions methods). I will take a look at the possibilities of implementing it and I will let you know if it's doable.
@axelheer
Ok, I've got a working POC. I will try to complete the implementation over the weekend. Could you provide more examples with let
, join
, group by
and query continuations for testing purposes?
Wow, that rocks. 🥇
I wouldn't expect it to work with more complex queries, but I looked for examples within some projects I'm involved in, which are too much verbose. Thus, I've written some examples using a simple n:m relation and a semantic relation too, which should cover those four use cases.
public class Tenant
{
public string Key { get; set; }
public string Description { get; set; }
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public IList<UserRequest> Requests { get; } = new List<UserRequest>();
public string Tenant { get; set; }
}
public class Request
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime TimeStamp { get; set; }
public string Category { get; set; }
public IList<UserRequest> Users { get; } = new List<UserRequest>();
}
public class UserRequest
{
public User User { get; set; }
public int UserId { get; set; }
public Request Request { get; set; }
public int RequestId { get; set; }
}
public class UserView
{
public int Id { get; set; }
public string Name { get; set; }
public int LastRequestId { get; set; }
public string LastRequestName { get; set; }
public DateTime LastRequestTimeStamp { get; set; }
}
public class TenantView
{
public string Key { get; set; }
public string Description { get; set; }
public int UserId { get; set; }
public string UserName { get; set; }
}
public class RequestsView
{
public int UserId { get; set; }
public string UserName { get; set; }
public int Year { get; set; }
public int Month { get; set; }
public int Count { get; set; }
}
public class RequestView
{
public int UserId { get; set; }
public string UserName { get; set; }
public int RequestId { get; set; }
public string RequestName { get; set; }
}
public static class Examples
{
public static IEnumerable<UserView> LetStatement(IEnumerable<User> users)
{
return from u in users
let ur = u.Requests.OrderBy(r => r.Request.TimeStamp).Last()
let r = ur.Request
select new UserView
{
Id = u.Id,
Name = u.Name,
LastRequestId = r.Id,
LastRequestName = r.Name,
LastRequestTimeStamp = r.TimeStamp
};
}
public static IEnumerable<TenantView> JoinStatement(IEnumerable<Tenant> tenants, IEnumerable<User> users)
{
return from t in tenants
join u in users on t.Key equals u.Tenant
select new TenantView
{
Key = t.Key,
Description = t.Description,
UserId = u.Id,
UserName = u.Name
};
}
public static IEnumerable<RequestsView> GroupStatement(IEnumerable<UserRequest> userRequests)
{
return from ur in userRequests
let u = ur.User
let r = ur.Request
group r by new
{
u.Id,
u.Name,
r.TimeStamp.Year,
r.TimeStamp.Month
}
into g
select new RequestsView
{
UserId = g.Key.Id,
UserName = g.Key.Name,
Year = g.Key.Year,
Month = g.Key.Month,
Count = g.Count()
};
}
public static IEnumerable<RequestView> QueryContinuation(IEnumerable<User> users, int year, int month, string category)
{
return from u in users
from ur in u.Requests
where ur.Request.TimeStamp.Year == year
&& ur.Request.TimeStamp.Month == month
&& ur.Request.Category == category
select new RequestView
{
UserId = u.Id,
UserName = u.Name,
RequestId = ur.Request.Id,
RequestName = ur.Request.Name
};
}
}
Hope this helps.
With such cryptic variable names it's impossible to create matches as you showed in the examples.
For example, this code can be generated when you change r
to lastRequest
public static IEnumerable<UserView> LetStatement(IEnumerable<User> users)
{
return from u in users
let ur = u.Requests.OrderBy(r => r.Request.TimeStamp).Last()
let r = ur.Request
select new UserView
{
Id = u.Id,
Name = u.Name,
LastRequestId = r.Id,
LastRequestName = r.Name,
LastRequestTimeStamp = r.TimeStamp
};
}
Better version:
return from u in users
let ur = u.Requests.OrderBy(r => r.Request.TimeStamp).Last()
let lastRequest = ur.Request
select new UserView
{
Id = u.Id,
Name = u.Name,
LastRequestId = lastRequest.Id,
LastRequestName = lastRequest.Name,
LastRequestTimeStamp = lastRequest.TimeStamp
};
@axelheer axelheer
Here's a pre-release version supporting linq
queries. I've also added support for matching against lazy variable's names aka acronym expanding
;) Simply speaking - now it's possible to match LastRequestTimeStamp
with lr.TimeStamp
. Could you install this version and test if it works according to your expectations?
❤️ Acronym expanding ❤️
Installing it will be the first thing on Monday morning, when I'm back at work.
Thank you!
Is there a way to complete LINQ statements too?
Currently, I get the options "Initialize with sample values" and "Initialize with local variables".
Some kind of "Initialize with 'p'" would be very nice.
Awesome project, btw.