I'm trying to split a string field and use the values in a calculation in a Select new so I can display the info in a report. The calculation is for the cubic meters of a package. The following code is what I'm using now but when I try to multiply the values from the split string I get an error:
Could not translate expression 'Parse(grp.Key.Length)' into SQL and could not treat it as a local expression
var res = (from packs in data
where packs.DispatchDate != null || (packs.DispatchDate >= DateTime.Parse(_dateFrom).Date &&
packs.DispatchDate <= DateTime.Parse(_dateTo).Date)
orderby packs.Production.DimensionMetric
group packs by
new
{
packs.DispatchDate,
packs.ProductType.TypeDetails,
packs.PackNo,
packs.Thickness,
Width = packs.Production.DimensionMetric.Substring(0,packs.Production.DimensionMetric.IndexOf('x')),
Length = packs.Production.DimensionMetric.Substring(packs.Production.DimensionMetric.IndexOf('x')+1),
packs.Sheets,
}
into grp
select new
{
grp.Key.DispatchDate,
grp.Key.TypeDetails,
grp.Key.PackNo,
grp.Key.Thickness,
grp.Key.Width,
grp.Key.Length,
grp.Key.Sheets,
CBM = ((int.Parse(grp.Key.Length)) * (int.Parse(grp.Key.Length))).ToString(),
}).ToList();
If I just assign or concat the values from Length and width to CBM there is no error, its only when I perform a math calculation on the 2 values. Can someone explain what needs to be done to make this work or do I have to come at it from a different angle?
var res = (from packs in data
where packs.DispatchDate != null || (packs.DispatchDate >= DateTime.Parse(_dateFrom).Date &&
packs.DispatchDate <= DateTime.Parse(_dateTo).Date)
orderby packs.Production.DimensionMetric
group packs by
new
{
packs.DispatchDate,
packs.ProductType.TypeDetails,
packs.PackNo,
packs.Thickness,
Width = packs.Production.DimensionMetric.Substring(0,packs.Production.DimensionMetric.IndexOf('x')),
Length = packs.Production.DimensionMetric.Substring(packs.Production.DimensionMetric.IndexOf('x')+1),
packs.Sheets,
}
into grp
select grp)
.AsEnumerable()
.Select(x=>new {
x.Key.DispatchDate,
x.Key.TypeDetails,
x.Key.PackNo,
x.Key.Thickness,
x.Key.Width,
x.Key.Length,
x.Key.Sheets,
CBM = ((int.Parse(x.Key.Length)) * (int.Parse(x.Key.Length))).ToString(),
})
.ToList();
Related
new to C#, SQL and Linq. I have two lists, one "dataTransactions" (fuel from gas stations) and a similar one "dataTransfers" (fuel from slip tanks).
They each access a different table from SQL and get combined later.
List<FuelLightTruckDataSource> data = new List<FuelLightTruckDataSource>();
using (SystemContext ctx = new SystemContext())
{
List<FuelLightTruckDataSource> dataTransactions
= ctx.FuelTransaction
.Where(tx => DbFunctions.TruncateTime(tx.DateTime) >= from.Date && DbFunctions.TruncateTime(tx.DateTime) <= to.Date
//&& tx.AssetFilled.AssignedToEmployee.Manager
&& tx.AssetFilled.AssignedToEmployee != null
//&
&& tx.AssetFilled.AssetType.Code == "L"
&& (tx.FuelProductType.FuelProductClass.Code == "GAS" || tx.FuelProductType.FuelProductClass.Code == "DSL"))
.GroupBy(tx => new { tx.AssetFilled, tx.DateTime, tx.FuelProductType.FuelProductClass, tx.FuelCard.FuelVendor, tx.City, tx.Volume, tx.Odometer}) //Added tx.volume to have individual transactions
.Select(g => new FuelLightTruckDataSource()
{
Asset = g.FirstOrDefault().AssetFilled,
Employee = g.FirstOrDefault().AssetFilled.AssignedToEmployee,
ProductClass = g.FirstOrDefault().FuelProductType.FuelProductClass,
Vendor = g.FirstOrDefault().FuelCard.FuelVendor,
FillSource = FuelFillSource.Transaction,
Source = "Fuel Station",
City = g.FirstOrDefault().City.ToUpper(),
Volume = g.FirstOrDefault().Volume,
Distance = g.FirstOrDefault().Odometer,
Date = g.FirstOrDefault().DateTime
})
.ToList();
In the end, I use
data.AddRange(dataTransactions);
data.AddRange(dataTransfers);
to put the two lists together and generate a fuel consumption report.
Both lists are individually sorted by Date, but after "AddRange" the "dataTransfers" just gets added to the end, losing my sort by Date. How do I sort the combined result again by date after using the "AddRange" command?
Try this:
data = data.OrderBy(d => d.Date).ToList();
Or if you want to order descending:
data = data.OrderByDescending(d => d.Date).ToList();
You can call List<T>.Sort(delegate).
https://msdn.microsoft.com/en-us/library/w56d4y5z(v=vs.110).aspx
Example:
data.Sort(delegate(FuelLightTruckDataSource x, FuelLightTruckDataSource y)
{
// your sort logic here.
});
Advantage: this sort doesn't create a new IList<T> instance as it does in OrderBy. it's a small thing, but to some people this matters, especially for performance and memory sensitive situations.
I have two collections, 'left' and 'right', having differing element types. The element types both have a string property 'paramNumber' which is not unique and the relationship via that is many to many. Now, there are two DateTime fields, 'left.date' and 'right.startDate'. For each selected 'left.date', I need to get the last element in 'right' where 'right.startDate' is smaller or equal (additionally to the join condition 'left.paramNumber' == 'right.paramNumber').
I wonder whether there is a direct way without full cross joins? I tried it with a sub query but got the problem with scoping of the 'lefty'' variable (see code).
I saw tutorials on the web doing a full cross-join first and then removing the undesired rows in the 'where' clause afterwards, but that is no option for us.
class left
{
public string paramNumber;
public DateTime date;
public string leftyName;
}
class right
{
public string paramNumber;
public DateTime startDate;
public string anotherString;
public DateTime timeOfDay;
}
class Program
{
static void Main(string[] args)
{
List<left> lefts = new List<left>();
List <right> rights = new List <right>();
//lefty not visible in the where clause...
//trying it with a second 'from right...' did not work because of
//casting problems.
var query =
from left lefty in lefts
join right righty in
((from right rightTmp in rights
where ((rightTmp.paramNumber == lefty.paramNumber) &&
(rightTmp.startDate <= lefty.date) &&
(rightTmp.anotherString == "N") )
select rightTmp
).ToList().Last())
on lefty.paramNumber equals righty.paramNumber
select new
{
myDate = lefty.date,
myLeftyName = lefty.leftyName,
myParamNumber = lefty.paramNumber,
myTimeOfDay = righty.timeOfDay
};
}
}
[Edit]: Solution (based on cechode's answer):
Below is the solution I currently use, based on cechode's answer.
The 'let' clause was the main missing piece, since it allows to reference l/lefty, too, not only r/rightTmp.
Finally, I did the full filtering to the one desired element within
'rights' directly in the first 'let' clause (by sorting ascending and using
Last(); of course cechode's descending/First() works, too) and spared the second one
with the 'toprightcheck' variable (I think cechode had good reasons for that null check, but I will try it with the shorter version):
var X = (from l in lefts
let topright =
(from r in rights
where r.paramNumber == l.paramNumber &&
r.startDate <= l.date
orderby r.startDate ascending
select r).Last()
select new {
lName = l.paramNumber,
rname = topright.paramNumber,
ldate = l.date,
rdate = topright.startDate });
does this do the trick for you?
var X = (from l in lefts
let topright = (from r in rights where r.paramNumber == l.paramNumber && r.startDate < l.date orderby r.startDate descending select r)
where topright!=null
let toprightcheck = topright.First()
select new { lName = l.paramNumber, rname = toprightcheck.paramNumber, ldate = l.date, rdate = toprightcheck.startDate });
Need help with linq query. I have a column which contains alphanumeric data in it and I want to extract numbers and perform mathematical comparisons. For example >,< etc.
So the data would be like: JS20, MRR12, DEEN2 etc.
I tried converting it to Int but it fails
var TheData = (from p in db.data.Where(l => Convert.ToInt16(l.TextAndNumber) <= 10)
group p by p.Names into g
select g.Key).ToList();
return Json(new { data = TheData });
Try something like this:
(from row in db.data
let digits = new String(row.TextAndNumber.Where(Char.IsDigit).ToArray())
let number = Int64.Parse(digits)
where number < 10
select row.Names
).Distinct();
You need to extract the numbers from the string before applying your conversion.
List<string> data = new List<string> { "JS20", "MRR112", "DEEN2" };
var TheData = data.Where(d => Convert.ToInt32(new string(d.Where(char.IsNumber).ToArray())) <= 10);
This returns DEEN2.
The following query gives me a barcode, version no of that barcode and an appcode. I would need the query to filter out duplicate barcodes and only keep the highest version number of that barcode.
I've been thinking along the way of merging the barcode field and the version field and only keep the highest but that seems dirty. Is there a cleaner solution?
select Barcode, MAX(versionNo) vn, Appcode from Mailsort
where Created between '01/26/2011' and '01/27/2011'
group by Barcode, AppCode;
The reason for this query is to get a LINQ statement.This does a count for every appcode regardless of the barcodes or the version at thye moment.
var results = from p in dataContext.GetTable<mailsortEntity>()
where p.Created > datetime && p.Created < datetime.AddDays(1)
group p by new { p.AppCode } into g
select new AppCodeCountEntity
{
AppCode = g.Key.AppCode,
Count = g.Count()
};
Is there a better solution than this LINQ code above?
var maxQuery =
from rh in MailSort
group rh by rh.BarCode into latest
select new { BarCode = latest.Key, MaxVersion = latest.Max(l => l.Version) }
;
var query =
from rh2 in MailSort
join max in maxQuery on new {rh2.BarCode, Version = rh2.Version }
equals new { max.BarCode, Version = max.MaxVersion }
select new { rh2.BarCode, rh2.Version, rh2.AppCode }
;
var barCodes = query.ToList();
I am trying to convert the following SQL into a LINQ expression
SELECT COUNT(ID) AS Count, MyCode
FROM dbo.Archive
WHERE DateSent>=#DateStartMonth AND DateSent<=#DateEndMonth
GROUP BY MyCode
and I have been trying to follow this webpage as an example:
Converting SQL containing top, count, group and order to LINQ (2 Entities)
I got this so far but I am stuck on understanding the new part
var res = (from p in db.Archives
where (p.DateSent>= dateStartMonth) && (p.DateSent< dateToday)
group p by p.MyCode into g
select new { ??????MyCode = g.something?, MonthlyCount= g.Count() });
Thanks in advance for helping
UPDATE:
can you explain what g.Key is? I dont understand where that variable came from or what it is referring too? I mean what if I group on 4 different things? How would I refer to each one?
var res = from archive in db.Archives
where archive.DateSent >= dateStartMonth &&
archive.DateSent < dateToday
group archive by archive.MyCode, archive.Extra into archiveGrp
select new
{
MyCode = archiveGrp.Key,
Extra = archiveGrp.???
MonthlyCount = archiveGrp.Count()
};
The LINQ statement below should work:
var res = from archive in db.Archives
where archive.DateSent >= dateStartMonth &&
archive.DateSent < dateToday
group archive by archive.MyCode into archiveGrp
select new
{
MyCode = archiveGrp.Key,
MonthlyCount = archiveGrp.Count()
};
Notice that the Key property will contain the value of the property that you group on, in this case MyCode.
from p in archive
where p.DateSent >= dateStartMonth && p.DateSent < dateToday
group p by p.MyCode into g
select new { Count = g.Count(), MyCode = g.Key }
produces the same output as your Sql in Linqpad