Inside a linq query to an anonymous select I want to concatenate strings from two properties.
For instance to find the full name of the oldest person in some grouping of persons.
var personsAndOldest = db.Persons.GroupBy(person => person.SomeThingThatCanBeGroupedForPerson).Select(a => new
{
FirstName = a.FirstOrDefault().FirstName,
LastName = a.FirstOrDefault().LastName,
BirthDate = a.FirstOrDefault().BirthDate,
FullnameOfOldes = a.Aggregate((pers1, pers2) => pers1.BirthDate > pers2.BirthDate ? pers1 : pers2).FirstName + " " //How do I get LastName of the old one (without using the full aggregate again)
});
Do I have to write the full aggregation again to get the LastName after the firstname and whitespace?
You could use a lambda statement in the Select:
var personsAndOldest = db.Persons.GroupBy(person => person.SomeThingThatCanBeGroupedForPerson).Select(a =>
{
var first = a.First();
var oldest = a.Aggregate((pers1, pers2) => pers1.BirthDate > pers2.BirthDate ? pers1 : pers2);
return new
{
FirstName = first.FirstName,
LastName = first.LastName,
BirthDate = first.BirthDate,
FullnameOfOldes = oldest.FirstName + " " + oldest.LastName)
};
});
You can do this as
var personsAndOldest = db.Persons
.GroupBy(person => person.SomeThingThatCanBeGroupedForPerson)
.Select(g => new
{
a = g.First(),
o = g.Aggregate((pers1, pers2) =>
pers1.BirthDate > pers2.BirthDate ? pers1 : pers2)
})
.Select(pair => new
{
FirstName = pair.a.FirstName,
LastName = pair.a.LastName,
BirthDate = pair.a.BirthDate,
FullnameOfOldes = pair.o.FirstName + " " + pair.o.LastName
});
You can use let to introduce new range variables.
You don't need to specify property name for anonymous type if it equals name of assigned property
I think OrderBy will find oldest person (but you can use aggregate and compare performance)
I believe that oldest person is one with minimal birth date, so you need to change aggregation to pers1.BirthDate < pers2.BirthDate ? pers1 : pers2
So
var personsAndOldest = from p in db.Persons
group p by p.SomeThingThatCanBeGroupedForPerson into g
let first = g.FirtOrDefault()
let oldest = g.OrderBy(x => x.BirthDate).FirstOrefault()
select
{
first.FirstName,
first.LastName,
first.BirthDate,
FullnameOfOldes = oldest.FirstName + " " + oldest.LastName
};
Related
I am trying to put the Column LANS from this multi column query into a list.
And the First and Last name into a separate list.
I just can't figure out how to make it work.
CODE:
//Resource
var ResourceFilter = _context.INT_CertificationsXREF.Include(i => i.RIM_Resource)
.Where(i => i.RIM_Resource.LAN == i.RIM_Resource.LAN)
.Where(i => i.Approved == true)
.Where(i => i.RIM_Resource.LAN != UserInformation.Globals.LANID)
.Select( i => i.RIM_Resource.FirstName + i.RIM_Resource.LastName + i.RIM_Resource.LAN)
.Distinct()
.ToList();
var ResourceFilterNames = ResourceFilter.RIM_Resource.Firstname + RIM_Resource.LastName.ToList();
var ResourceFilterLANS = ResourceFilter.RIM_Resource.LAN.ToList();
Desired OutPut
ResourceFilterNames = Firstname" "Lastname, Firstname" "Lastname, ect....
ResourceFilterLANS = NQ90, RE97, I3R9, ect.
The list also need to be in sync order wise.
If I understood your question...i think what you want is:
var ResourceFilter = _context.INT_CertificationsXREF.Include(i => i.RIM_Resource)
.Where(i => i.RIM_Resource.LAN == i.RIM_Resource.LAN)
.Where(i => i.Approved == true)
.Where(i => i.RIM_Resource.LAN != UserInformation.Globals.LANID)
.Select( i => new {
fullName = i.RIM_Resource.FirstName + " " + i.RIM_Resource.LastName,
Lan = i.RIM_Resource.LAN
})
.Distinct()
.ToList();
the you can retrieve the list of "fullNames" and "LANS" like this
List<string> fullNames = ResourceFilter.Select(x => x.fullName).ToList();
List<string> LANS = ResourceFilter.Select(x => x.Lan).ToList();
hope it helps
Based on your desired output I think this solution will work for you
var ResourceFilterNames= string.Join(",", ResourceFilter.Select(x => ( x.Firstname
+ " " + x.LastName )));
var ResourceFilterLANS = string.Join(",", ResourceFilter.Select(x=> x.Lan));
In order this solution to work you should delete Select from ResourceFilter or rewrite it like below:
.Select( i => new { i.RIM_Resource.FirstName, i.RIM_Resource.LastName, i.RIM_Resource.LAN})
I will use the following class as my test input:
public class MyData
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Lan { get; set; }
}
My first solution assumes that your combination of FirstName and LastName is unique.
To hold your two lists in sync I will use a dictionary:
// var resource = new List<MyData>();
var dictionary = resource.ToDictionary(r => r.FirstName + r.LastName, r => r.Lan);
My second solution assumes that they are not unique so you can use this:
var dictionary = new Dictionary<string, List<string>>();
foreach(var res in resource)
{
var key = res.FirstName + res.LastName;
List<string> value;
if ( dictionary.TryGetValue(key, out value))
{
value.Add(res.Lan);
}
else
{
dictionary[key] = new List<string> {res.Lan};
}
}
I've attempted to write this query two different ways, and no matter how I write it, I can't get the join to pan out. It just keeps tossing "The method or operation is not implemented." at me. What I'm trying to do is, in SQL, simple: Obtain a list of items from table A (below - Customer) where there is no corresponding listing in table B (below - SalesReps).
Attempted Lamda:
var customers =
_sms.CurrentSession.Query<customer>()
.GroupJoin(_sms.CurrentSession.Query<salesReps>(),
c => c.Id,
sr => sr.CustomerId,
(x, y) => new {c = x, sr = y})
.SelectMany(xy => xy.sr.DefaultIfEmpty(),
(x, y) => new {c = x.c, sr = y})
.Where(data => data.sr.SalesRepId == null)
.Select(data => new CustomerDTO
{
Id = data.c.Id,
FullName = data.c.FirstName + " " + data.c.LastName,
FirstName = data.c.FirstName,
LastName = data.c.LastName
});
var custList = customers .ToList();
Attempted Query Syntax:
var customers = from c in _sms.CurrentSession.Query<customer>()
join sr in _sms.CurrentSession.Query<salesReps>()
on c.Id equals sr.CustomerId
into joinedData
from jd in joinedData.DefaultIfEmpty()
where c.IsEmployee == false
&& c.CustomerOptions.Company.Id == companyGuid
&& jd.SalesRepId == null
select
new CustomerDTO
{
Id = c.Id,
FullName = c.FirstName + " " + c.LastName,
FirstName = c.FirstName,
LastName = c.LastName
};
var custList = customers .ToList();
I get the impression that the issue is on the check for null sales reps, but I'm not sure.
my code:
//get data
var myData = from log in db.OperationLogs
group log by log.CreateTime.Date into g
orderby g.Key
select new { CreateTime = g.Key, Count = g.Count() };
this code will throw an exception like entity framework does not support get Date operation.
because log.createtime both have date and time, i want to group by date, how should i do
Use EntityFunctions.TruncateTime Method (Nullable<DateTime>). It will be transalated into TRUNCATETIME() TSQL function in generated SQL query, which does what you need:
Returns the expression, with the time values truncated.
So your code should be as follows:
//get data
var myData = from log in db.OperationLogs
group log by EntityFunctions.TruncateTime(log.CreateTime) into g
orderby g.Key
select new { CreateTime = g.Key, Count = g.Count() };
Here is an easier way to do it for later Entity Framework versions.
var query = Data
.GroupBy(o => new { EventDate = o.EventDate.Date })
.Select(s => new SalesData()
{
EventDate = s.Key.EventDate,
Amount = s.Sum(o => o.Amount),
Qty = s.Sum(o => o.Qty),
RefundAmount = s.Sum(o => o.RefundAmount),
RefundQty = s.Sum(o => o.RefundQty),
})
.OrderBy(o => o.EventDate)
.ToList();
return query;
var result = from s in entitiesModel.TvysFuelTankDatas
orderby s.Datetime ascending
group s by new { y = s.Datetime.Year, m = s.Datetime.Month + "/", d = s.Datetime.Day + "/" } into g
select new WellDrillData { Date = Convert.ToDateTime(g.Key.d.ToString() + g.Key.m.ToString() + g.Key.y.ToString()), Depth = (double)g.Sum(x => x.Difference) };
List<WellDrillData> dailyFuelConsumptions = result.ToList();
Is it possible to compute 'on-the-fly' Division based on Department and JobTitle
with eventually applying some Transformations such as concatenating
in the chained linq query below ?
public static List<Developer> GetDevelopersData(List<Employee> employees)
{
List<Developer> developers =
employees.Where(x => x.Department == "Dev")
.Select(x => new Developer
{
Name = x.Name,
Department = x.Department,
JobTitle = x.Function,
Division = "Department" + "/" + "Function" // based on previous properties
}).ToList();
return developers;
}
I suppose Function and Departement are string type ?
List<Developer> developers =
employees.Where(x => x.Department == "Dev")
.Select(x => new Developer
{
Name = x.Name,
Department = x.Department,
JobTitle = x.Function,
Division = String.Concat(x.Function, "/", x.Department)
}).ToList();
return developers;
Unless I'm missing something, you could do:
Division = string.Format("{0}/{1}", x.Department, x.Function)
Assuming you just want the two properties concatenated into a string.
to compute on the fly, you can use let
(from x in employees
let MyFunction=String.Concat(x.Function, "/", x.Department)//you can use whatever you want here
select new Developer()
{
Name = x.Name,
Department = x.Department,
JobTitle = x.Function,
Division = x.MyFunction
}).ToList();
How do I do sorting when generating anonymous types in linq to sql?
Ex:
from e in linq0
order by User descending /* ??? */
select new
{
Id = e.Id,
CommentText = e.CommentText,
UserId = e.UserId,
User = (e.User.FirstName + " " + e.User.LastName).Trim()),
Date = string.Format("{0:d}", e.Date)
}
If you're using LINQ to Objects, I'd do this:
var query = from e in linq0
select new
{
Id = e.Id,
CommentText = e.CommentText,
UserId = e.UserId,
User = (e.User.FirstName + " " + e.User.LastName).Trim()),
Date = e.Date.ToString("d")
} into anon
orderby anon.User descending
select anon;
That way the string concatenation only has to be done once.
I don't know what that would do in LINQ to SQL though...
If I've understood your question correctly, you want to do this:
from e in linq0
order by (e.User.FirstName + " " + e.User.LastName).Trim()) descending
select new
{
Id = e.Id,
CommentText = e.CommentText,
UserId = e.UserId,
User = (e.User.FirstName + " " + e.User.LastName).Trim()),
Date = string.Format("{0:d}", e.Date)
}
Would this work, as a way of avoiding Jon's select...into?
from e in linq0
let comment = new
{
Id = e.Id,
CommentText = e.CommentText,
UserId = e.UserId,
User = (e.User.FirstName + " " + e.User.LastName).Trim()),
Date = string.Format("{0:d}", e.Date)
}
orderby comment.User descending
select comment
I'm going to get a necromancer badge for this answer, but I still think it's worth showing this snippet.
var records = await (from s in db.S
join l in db.L on s.LId equals l.Id
where (...)
select new { S = s, Type = l.MyType }
).ToListAsync();
//Data is retrieved from database by now.
//OrderBy below is LINQ to Objects, not LINQ to SQL
if (sortbyABC)
{
//Sort A->B->C
records.OrderBy(sl => sl.Type, new ABC());
}
else
{
//Sort B->A->C
records.OrderBy(sl => sl.Type, new BAC());
}
ABC and BAC implement IComparer<MyType>.