SQL query run OK:
select o.OpName,isnull(Amount,0) from Setup_tblOperator o
left join
(
select t.opid,sum(isnull(t.Amount,0)) Amount from
Load_tblTransaction t
where cast(t.RequestTime as date)='2017-04-24'
group by t.opid
) t on t.OpId=o.OpId
where o.IsActive=1
I tried following code in LINQ to SQL:
var trans = (from o in mouDataEntities.Setup_tblOperator
join t in mouDataEntities.Load_tblTransaction
on o.OpId equals t.OpId into ot
from n in ot.Where(
t => DbFunctions.TruncateTime(t.RequestTime) ==
DbFunctions.TruncateTime(seldate))
.DefaultIfEmpty()
select new
{
Operator = o.OpName,
Amount= n.Amount
});
var gt = trans.GroupBy(t => t.Operator)
.Select(n => new { Operator = n.Key, Amount = n.Sum(a=>a.Amount) })
.ToList();
It throws an error:
The cast to value type 'System.Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
There are a few cases where the straightforward SQL to C# translation gets accepted, but fails at run-time. In C#, set.DefaultIfEmpty().Select(n => n.Amount)
, where n.Amount
has type int
, would have a result type IEnumerable<int>
. It would fail with a NullReferenceException
if set
were empty, because in that case n
would become null
as well. Therefore, there is no reason why you'd need int?
, since you can't ever get null
as a result.
In SQL, it's not so easy. Retrieving a column of the default row introduced by LEFT JOIN
is valid, and produces NULL
.
But the C# code is expecting a value of type int
, and an int
can't be null
.
You need to find some way to trick the type system so that you can specify how null
should be handled. A simple cast suffices:
Change
Amount = n.Amount
to
Amount = (int?) n.Amount
Or, to turn null
into 0
,
Amount = (int?) n.Amount ?? 0
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.