I hope you can help me to my code after I change the data type of the following I get this exception "Sequence contains no matching element exception. ". And I am sure this because of FirstOrDefault() Extension.
LandId - long
ShowMapPoint - string
Development - string
Location - string
MapPointX - string
MapPointY - string
AreaSize - from decimal? into long?
Premium - from decimal? into long?
TransactionPrice - from decimal? into long?
This is my code:
var result = _context.DwPropertyMasters.Where(x => x.ShowMapPoint == "Y")
.Select(x => new
{
x.LandId,
a = x.Development == null || x.Development == "" ? x.Location : x.Development,
x.MapPointX,
x.MapPointY,
AreaSize = x.AreaSize ?? 0,
Premium = x.Premium ?? 0,
b = (x.Premium == 0 ? null : x.Premium) * 100000000 / (x.AreaSize == 0 ? null : x.AreaSize) ?? 0,
c =
_context.DwPropertyDetails.Where(
z => (z.TransactionPrice > 0 || z.TransactionPrice != null) && z.LandId == x.LandId)
.GroupBy(z => z.LandId)
.Select(g =>
(g.Sum(p => p.TransactionPrice) == 0 ? null : g.Sum(p => p.TransactionPrice)) /
(g.Sum(p => p.ActualSize) == 0 ? null : g.Sum(p => p.ActualSize)) ?? 0)
.FirstOrDefault(),
d =
((x.AreaSize2 == 0 ? null : x.AreaSize2) == 0
? 0
: (x.Premium == 0 ? null : x.Premium) * 100000000 / (x.AreaSize2 == 0 ? null : x.AreaSize2)) ??
0,
x.LandType,
e =
_context.DwPropertyDetails.Where(
y => (y.TransactionPrice > 0 || y.TransactionPrice != null) && y.LandId == x.LandId)
.Select(y => new
{
a = 1
}).Count()
});
Your problem is in the sum of the Premium and TransactionPrice
If you grouping doesn't contain an item with a value, then it will try to sum null values. That can't work.
I would change it as follows:
(g.All(p => p.TransactionPrice == null) ? null : g.Where(p => p.TransactionPrice != null).Sum(p => p.TransactionPrice))
and
(g.All(p => p.ActualSize == null) ? null : g.Where(p => p.ActualSize != null).Sum(p => p.ActualSize)))
First check if everything is null, then it is null, else sum the values.
But you need to edit your code further, your current code would enable situations like 123 / null or null / 123. Which would also be a exception.
It is hard to understand what you are doing. It is way too complex with all these inline if's. And on line 13 you have:
z.TransactionPrice > 0 || z.TransactionPrice != null.
You might as well remove z.TransactionPrice > 0, because the second part allows all values (not null), including everything smaller than 0.
The 'Sequence contains no matching element' exception is typically something I'd expect when you use .First(). Not .FirstOrDefault().
Based on your code and what I think you want to achieve I have rewritten the query:
var result = _context.DwPropertyMasters.Where(x => x.ShowMapPoint == "Y")
.Select(x => new
{
x.LandId,
a = x.Development == null || x.Development == "" ? x.Location : x.Development,
x.MapPointX,
x.MapPointY,
AreaSize = x.AreaSize ?? 0,
Premium = x.Premium ?? 0,
b = (x.AreaSize == 0) ? 0 : (x.Premium * 100000000 / x.AreaSize ?? 0),
c = _context.DwPropertyDetails.Where(z => z.TransactionPrice > 0 && z.LandId == x.LandId)
.GroupBy(z => z.LandId)
.Select(g => g.Sum(p => p.ActualSize) == 0 ? 0 : (g.Sum(p => p.TransactionPrice) / g.Sum(p => p.ActualSize) ?? 0)
.FirstOrDefault(),
d = (x.AreaSize2 == 0) ? 0 : (x.Premium * 100000000 / x.AreaSize2 ?? 0),
x.LandType,
e = _context.DwPropertyDetails.Count(y => y.TransactionPrice > 0 && y.LandId == x.LandId)
});
I do not know if this works as you intended (and works at all since I didn't test this), but it is shorter and I hope more readable.
Keep in mind that this query is executed in sql server, so there is no need to check for null values. The only thing that must be prevented is to divide by zero. If we consider the next line:
b = (x.AreaSize == 0) ? 0 : (x.Premium * 100000000 / x.AreaSize ?? 0)
If:
x.AreaSize is null then (x.Premium * 100000000 / null ?? 0) => null ?? 0 => 0.
x.AreaSize = 0 then the result = 0.
x.Premium is null then the result is null / value ?? 0 => null ?? 0 => 0.
x.Premium = 0 then the result = 0.
Related
I'm trying to do this in LINQ.
Can you guys help me to do this?
There some tool to help me with this conversion?
SELECT
CODIGO_DEPENDENCIA,
SUM(COALESCE(LOCAL_MOVEL, 0)) AS LOCAL_MOVEL,
SUM(COALESCE(LOCAL_FIXO, 0)) AS LOCAL_FIXO,
SUM(COALESCE(DDD_MOVEL, 0)) AS DDD_MOVEL,
SUM(COALESCE(DDD_FIXO, 0)) AS DDD_FIXO,
SUM(COALESCE(EXTERNA_INTERNACIONAL, 0)) AS EXTERNA_INTERNACIONAL
FROM (
SELECT
CODIGO_DEPENDENCIA,
CASE WHEN TIPO = 'SELM' THEN SUM(VALOR) END AS LOCAL_MOVEL,
CASE WHEN TIPO = 'SELF' THEN SUM(VALOR) END AS LOCAL_FIXO,
CASE WHEN TIPO = 'SENM' THEN SUM(VALOR) END AS DDD_MOVEL,
CASE WHEN TIPO = 'SENF' THEN SUM(VALOR) END AS DDD_FIXO,
CASE WHEN TIPO = 'SEI' THEN SUM(VALOR) END AS EXTERNA_INTERNACIONAL
FROM CAD_BILHETES
WHERE ID_PRODUTO IS NULL
AND ID_COMPETENCIA = 60
AND CODIGO_DEPENDENCIA IN (14, 160)
AND TIPO IN ('SEI', 'SELM', 'SENF', 'SELF', 'SENM')
AND VALOR <> 0
GROUP BY TIPO,CODIGO_DEPENDENCIA
) TAB
GROUP BY CODIGO_DEPENDENCIA
Obviously untested. Also, uncertain if null tests are needed or how they will react through SQL translation. It may be preferable to change the first query to return 0 when not matching and then just sum the results, but I wasn't sure the datatype of the columns.
var tab = from cb in CAD_BILHETES
where cb.ID_PRODUTO == null && cb.ID_COMPETENCIA == 60 && (new[] { 14, 160 }).Contains(cb.CODIGO_DEPENDENCIA) &&
(new[] { "SEI", "SELM", "SENF", "SELF", "SENM" }).Contains(cb.TIPO) && cb.VALOR != 0
group cb by new { cb.TIPO, cb.CODIGO_DEPENDENCIA } into cbg
select new { cbg.Key.CODIGO_DEPENDENCIA,
LOCAL_MOVEL = (cbg.Key.TIPO == "SELM" ? cbg.SUM(cb => cb.VALOR) : null),
LOCAL_FIXO = (cbg.Key.TIPO == "SELF" ? cbg.SUM(cb => cb.VALOR) : null),
DDD_MOVEL = (cbg.Key.TIPO == "SENM" ? cbg.SUM(cb => cb.VALOR) : null),
DDD_FIXO = (cbg.Key.TIPO == "SENF" ? cbg.SUM(cb => cb.VALOR) : null),
EXTERNA_INTERNACIONAL = (cbg.Key.TIPO == "SEI" ? cbg.SUM(cb => cb.VALOR) : null),
};
var ans = from cb in tab
group cb by cb.CODIGO_DEPENDENCIA into cbg
select new {
CODIGO_DEPENDENCIA = cbg.Key,
LOCAL_MOVEL = cbg.Sum(cb => cb.LOCAL_MOVEL == null ? 0 : cb.LOCAL_MOVEL),
LOCAL_FIXO = cbg.Sum(cb => cb.LOCAL_FIXO == null ? 0 : cb.LOCAL_FIXO),
DDD_MOVEL = cbg.Sum(cb => cb.DDD_MOVEL == null ? 0 : cb.DDD_MOVEL),
DDD_FIXO = cbg.Sum(cb => cb.DDD_FIXO == null ? 0 : cb.DDD_FIXO),
EXTERNA_INTERNACIONAL = cbg.Sum(cb => cb.EXTERNA_INTERNACIONAL == null ? 0 : cb.EXTERNA_INTERNACIONAL)
};
The Code: It highlights the bottom most part where I can trying to tell Linq to find the shipto column and update the datetimestamp on the other table by a certain amount of minutes and tells me that I cannot implicitly convert type 'System.DateTime?' to 'int?' and I am unsure of how to continue...
var TestingLinq = (from a in db.shp_master
join b in db.shp_status on a.serialnbr equals b.serialnbr into b_join
from b in b_join.DefaultIfEmpty()
where
a.shipto == "1022a" &&
a.status == "s" &&
b.status == "s" &&
a.shpreq == 0
group new {a, b} by new {
a.serialnbr,
a.trailer,
a.shipto
} into g
orderby
g.Key.serialnbr
select new RecieveTruck {
SerialNumber = g.Key.serialnbr,
TrailerNumber = (g.Key.trailer ?? "N/A"),
Shipped = g.Min(p => p.b.datetimestamp),
ETA =
g.Key.shipto == "1026" ? (System.DateTime?)Convert.ToDateTime(g.Min(p => p.b.datetimestamp)).AddMinutes(180) :
g.Key.shipto == "2020" ? (System.DateTime?)Convert.ToDateTime(g.Min(p => p.b.datetimestamp)).AddMinutes(195) :
g.Key.shipto == "2017" ? (System.DateTime?)Convert.ToDateTime(g.Min(p => p.b.datetimestamp)).AddMinutes(180) :
g.Key.shipto == "nor" ? (System.DateTime?)Convert.ToDateTime(g.Min(p => p.b.datetimestamp)).AddMinutes(180) : null
});
return View(TestingLinq);
Gives me the error in the title....
I was trying to convert this SQL Query to Linq:
SELECT a.serialnbr, ISNULL(a.trailer, 'N/A') AS 'trailer', MIN(b.datetimestamp) AS 'datetimestamp',
CASE WHEN a.shipto = '1026' THEN DATEADD(mi, 180, MIN(b.datetimestamp))
WHEN a.shipto = '2020' THEN DATEADD(mi, 195, MIN(b.datetimestamp))
WHEN a.shipto = '2017' THEN DATEADD(mi, 180, MIN(b.datetimestamp))
WHEN a.shipto = 'nor' THEN DATEADD(mi, 180, MIN(b.datetimestamp))
ELSE NULL END AS 'eta'
FROM shp_master AS a LEFT OUTER JOIN shp_status AS b ON a.serialnbr = b.serialnbr
WHERE a.shipto = '1022a' AND a.status = 's' AND b.status = 's' AND a.shpreq = 0
GROUP BY a.serialnbr, a.trailer, shipto
ORDER BY a.serialnbr
In your comment, you specified that RecieveTruck.ETA is an int?, but you're assigning it by doing
ETA = g.Key.shipto == "1026" ? (System.DateTime?)Convert.ToDateTime(g.Min(p => p.b.datetimestamp)).AddMinutes(180) :
g.Key.shipto == "2020" ? (System.DateTime?)Convert.ToDateTime(g.Min(p => p.b.datetimestamp)).AddMinutes(195) :
g.Key.shipto == "2017" ? (System.DateTime?)Convert.ToDateTime(g.Min(p => p.b.datetimestamp)).AddMinutes(180) :
g.Key.shipto == "nor" ? (System.DateTime?)Convert.ToDateTime(g.Min(p => p.b.datetimestamp)).AddMinutes(180) : null
And that will resolve to a DateTime?. You'll need to choose one or the other. It looks like you're looking for ETA to be a DateTime?, though, so I'd just change that property type and you should be good to go.
I have the following LINQ statement which is calculating 3 values from a data table. Sometimes some of these values may contain null. How do i do the equivalent of coalescing the null to a 0.
var striko2scrap = from myrow in Scrap.AsEnumerable()
where myrow.Field<string>("MachineID") == "Striko 2"
group myrow by myrow.Field<string>("MachineID") == "Striko 2" into g
select new
{
TotalScrap = g.Sum(x => x.Field<int?>("Runners") ??
0 + x.Field<int?>("HouseIngots") ??
0 + x.Field<int?>("Other") ??
0)
} ;
I have tried the ?? 0 in different places but when I debug I still get the same result.
The problem you face is operator precedence. I think what you want to do is handle a null as 0. That would be:
int? a = null;
int? b = 1;
int? c = 2;
int result = (a ?? 0) + (b ?? 0) + (c ?? 0); // 3
What you wrote is the equivalent of
int result = a ?? (0 + b) ?? (0 + c) ?? 0; // 1
So all you have to do is to modify the g.Sum(x => ...) and it should work as intended.
I personally like using the HasValue and Value properties of nullable value types, which would be:
select new
{
TotalScrap = g.Sum(x =>
(x.Field<int?>("Runners").HasValue ? x.Field<int?>("Runners").Value : 0 ) +
(x.Field<int?>("HouseIngots").HasValue ? x.Field<int?>("HouseIngots").Value : 0 ) +
(x.Field<int?>("Other").HasValue ? x.Field<int?>("Other").Value : 0 )
)};
But if you like the ?? notation you could use:
select new
{
TotalScrap = g.Sum(x =>
(x.Field<int?>("Runners") ?? 0 ) +
(x.Field<int?>("HouseIngots") ?? 0 ) +
(x.Field<int?>("Other") ?? 0 )
)};
Try this:
var striko2scrap = from myrow in Scrap.AsEnumerable()
where myrow.Field<string>("MachineID") == "Striko 2"
group myrow by myrow.Field<string>("MachineID") == "Striko 2" into g
select new
{
TotalScrap = g.Sum(x =>
(x.Field<int?>("Runners") ?? 0) +
(x.Field<int?>("HouseIngots") ?? 0) +
(x.Field<int?>("Other") ?? 0))
} ;
Have you tried
x.Field<int?>("Runners").Value ?? 0
or
x.Field<int?>("Runners").HasValue ? x.Field<int?>("Runners") : 0
in my DB, I have e.g. 13 orders.
The code below returns all of them, if the OrderID = 0 and CustomerName = "lorem".
If I comment the line (OrderID == 0) ?.... it works fine. What's wrong ?
var result = (from x in db.Order
where
(OrderID == 0) ? x.OrderID > 0 : x.OrderID == OrderID
&&
(string.IsNullOrEmpty(CustomerName)) ?
!string.IsNullOrEmpty(CustomerName)
:
x.User.Name.Contains(CustomerName)
select x)
.ToList();
I think you can not define conditional condition inside LINQ query in this way, what you can do is, for example:
var result = (from x in db.Order where
((OrderID == 0 && x.OrderID > 0) ||
(OrderID != 0 && x.OrderID == OrderID))
&&
(string.IsNullOrEmpty(CustomerName)) ?
!string.IsNullOrEmpty(CustomerName)
:
x.User.Name.Contains(CustomerName)....
I have the query:
var qq = (from c in db.tblArcadeGames
where
c.IsDeleted == false &&
c.ParentGameID == 0 &&
c.Approved == true
let aggPlays = c.Plays + db.tblArcadeGames.Where(v => v.ParentGameID == c.ID).Sum(v => (int?)v.Plays)
orderby aggPlays descending
select new { c, aggPlays })
.Skip(Skip)
.Take(Fetch);
foreach (var g in qq)
{
HttpContext.Current.Response.Write("{" + g.aggPlays + "}\n");
}
When I print out aggPlays in the loop above they come out as:
{21}
{}
{}
{}
The problem seems to be that the Sum() returns null if no records exist. I'm not sure how to get around this so that c.Plays + null wont equal null but just c.Plays.
You can correct this by not returning int?, but rather convert to an int directly:
.Sum(v => v.Plays ?? 0)
int response =
(from p in data.tbHoraires
where p.eid == eid && p.annee == annee && p.obligatoire == true
select (int?)p.nbminute ?? 0).Sum();