Linq, exclude SQL Nulls - c#

I'm generating a pie chart, currently I have have the following variable, How to exclude Null records? it works but it includes null values in the pie chart
var PieChartData1 = from T1 in Result
group T1 by T1.Reasons into G1
orderby count ascending
select new { G1.Key, Count = G1.Count() };
obj.peichart1 = PieChartData1.ToArray();

if T1 is Nullable use HasValue Property
var PieChartData1 = from T1 in Result
where T1.HasValue
group T1 by T1.Reasons into G1
orderby count ascending
select new { G1.Key, Count = G1.Count() };

Add a where clause to filter the null values before you use them - here I'm assuming that either T1 or T1.Reasons can be null:
var PieChartData1 = from T1 in Result
where T1 != null && T1.Reasons != null
group T1 by T1.Reasons into G1
orderby count ascending
select new { G1.Key, Count = G1.Count() };
I also suspect that orderby count ascending should be orderby G1.Count() ascending.

You can also write it using lambda expressions:
var pieChartData = Result.Where(r => r.Reason != null)
.GroupBy(r => r.Reason)
.OrderBy(g => g.Count())
.Select(g => new { g.Key, Count = g.Count() });

Related

Linq Dynamic Query With Group By

I need extra where clause for my Linq query. For example if customer choose a date filter so i need to date filter to my query etc... When i try to myQuery.Where predicate there is visible just group by's field.
How can i append new where condition to my query.
//for example i need dynamically append o.OrderDate==Datetime.Now or another where clause
var myQuery =(from o in _db.Orders
join l in _db.OrderLines.Where(x => x.ParaBirimi == model.ParaBirimi) on o.orderId equals
l.OrderId
where o.OrderDate.Value.Year == year1
group o by new {o.OrderDate.Value.Month}
into g
select
new
{
Month = g.Key.Month,
Total = g.Select(t => t.OrderLines.Sum(s => s.OrderTotal)).FirstOrDefault()
});
You are too late at the end of the query to add new Where. You have already grouped the data, and projected it, removing nearly all the fields.
Try:
var baseQuery = from o in _db.Orders
join l in _db.OrderLines.Where(x => x.ParaBirimi == model.ParaBirimi) on o.orderId equals l.OrderId
where o.OrderDate.Value.Year == year1
select new { Order = o, OrderLine = l };
if (something)
{
baseQuery = baseQuery.Where(x => x.Order.Foo == "Bar");
}
var myQuery = (from o in baseQuery
group o by new { o.Order.OrderDate.Value.Month }
into g
select
new
{
Month = g.Key.Month,
Total = g.Sum(t => t.OrderLine.OrderTotal)
});
Clearly you can have multiple if. Each .Where() is in && (AND) with the other conditions.
Note how the result of the join is projected in an anonymous class that has two properties: Order and OrderLine

Linq query with toDictionary

I have the following linq query
var temp = (from p in db.BEM_EVT_FULL
where (p.date_reception > dt)
group p by p.mc_object into g
orderby g.Count() descending
select new StringIntType
{
str = g.Key,
nbr = g.Count()
}).Take(50).ToList();
Instead of casting result to StringIntType i need to use Dictionary with int and string types.
You could try something like this:
var temp = (from p in db.BEM_EVT_FULL
where (p.date_reception > dt)
group p by p.mc_object into g
orderby g.Count() descending
select new
{
Key = g.Key,
Value = g.Count()
}).Take(50)
.ToDictionary(x=>x.Key, y=>y.Value);
it looks like there may be an answer for this question here: Convert Linq Query Result to Dictionary
basically, instead of ToList use ToDictionary
.ToDictionary( t => t.Key, t => t.Value);

LEFT JOIN with OR condition in LINQ

I need to write following T-SQL in LINQ:
SELECT T1.ID, T2.Name
FROM T1
LEFT JOIN T2 ON (T1.ID = I2.ID1 OR T1.ID = T2.ID2)
An OR-join would look like this in LINQ:
T1.Join(T2, t1=>new{}, t2=>new{}, (t1,t2)=>new{ID=t1.Id, t2=t2}).Where(o=>o.Id == o.t2.Id1 || o.Id==o.t2.Id2);
But that query is an INNER JOIN, not a LEFT JOIN.
Some kind of LEFT JOIN would look like this:
T1.GroupJoin(T2, t1 => t1.Id, t2 => t2.Id1, (t1, t2) => new { Id = t1.Id, Name1 = t2.Select(t => t.Name) }).DefaultIfEmpty()
.GroupJoin(T2, o => o.Id, t2 => t2.Id2, (i, j) => new { Id = i.Id, Name1 = i.Name1, Name2 = j.Select(t => t.Name) }).DefaultIfEmpty();
This query produces correct results, but makes 2 joins instead of 1. Or is it really equivalent to original T-SQL?
Does anybody know how to rewrite this query better?
This answer from a similar question gives us an easy way to write LEFT JOINs:
https://stackoverflow.com/a/4739738/1869660
var query = from t1 in T1
from t2 in T2.Where(tt2 => (t1.ID == tt2.ID1) || (t1.ID = tt2.ID2))
.DefaultIfEmpty()
select new { t1.ID, t2.Name }
To solve this with single linq, try using cross join
var results = (from a in test1
from b in test2
where a.ID == b.ID1 || a.ID == b.ID2
select new {x = a.ID, y = b.Name});
var LeftJoin = from emp in ListOfEmployees
join dept in ListOfDepartment
on emp.DeptID equals dept.ID into JoinedEmpDept
from dept in JoinedEmpDept.DefaultIfEmpty()
select new
{
EmployeeName = emp.Name,
DepartmentName = dept != null ? dept.Name : null
};

transform sql to linq with join, group-by and where

I have the following sql, which I want to convert to linq
SELECT Contrato.finca, SUM(Pago.Importe_subtotal)
FROM Pago, Contrato
WHERE Pago.Contrato = Contrato.ID AND Pago.pagado = 1
GROUP BY Contrato.finca
ORDER BY 2 DESC
GO
What I have now in linq is the following, but the group by doesn't work.
var x = from contrato in ctx.Contratos
join pago in ctx.Pagos
on contrato.ID equals pago.Contrato
where pago.pagado == true
group contrato by contrato.finca
select contrato.Finca1;
Think this should work:
ctx.Pagos.Where(m=>m.pagado==true).GroupBy(m=>m.Contrato.finca)
.Select(m=> new { Id= m.Key, Val= m.Sum(n => n.Importe_subtotal)})
Try
var x = from contrato in ctx.Contratos
join pago in ctx.Pagos
on contrato.ID equals pago.Contrato
where pago.pagado == true
group new {contrato, pago} by contrato.finca into g
select new {
key = g.Key,
sum = g.Sum(p => p.pago.Importe_subtotal)
};

Grouping 2 Tables, Counting Values And Then Saving The Results In A Dictionary

So I have an SQL statement looks like this
SELECT T1.NAME, COUNT(T2.VALUE) AS numInstances
FROM TABLE2 T2 LEFT OUTER JOIN
TABLE1 T1 on T2.NAME_ID = T1.NAME_ID
WHERE (T2.DATE BETWEEN to_date('01-Aug-2011', 'dd-mon-yyyy')
AND to_date('31-Aug-2011' , 'dd-mon-yyyy')) AND T2.VALUE = 1))
GROUP BY T1.NAME
This statement looks for when names to match in the 2 tables and then find all '1' values (these relate to something like sick day, worked, day off, ect) in the month of august and then count how many of each I have. This SQL statement works great but I'm using MVC .NET in C# and need this to be a LINQ statement that generates a Dictionary.
So i would like the Dictionary to look something like,
NAME VALUECOUNT
John 8
Joe 1
Eric 0
I've tried
Dictionary<string,int> results =
(from t2 in db.table2.Where(t2 => m.Value == 1)
from t1 in db.table1
where(t2.DATE >= new DateTime(2011,8,1) && t2.DATE <= new DateTme(2011,8,31)
orderby t1.NAME
group new{T2, T1} by new {t2.VALUE, t1.NAME} into g
select new {
new KeyValuePair<string,int>(
g.Key.NAME,
(int)g.sum(g => g.Key.Value))
}).AsEnumerable().ToDictionary();
Ideas?
using(DbEntities db = new DbEntities())
{
var fromDate = new DateTime(2011,8,1);
var toDate = new DateTime(2011,8,31);
var dictionary =
(from t1 in db.TABLE1
join t2 in db.TABLE2.Where(x => x.VALUE == 1 && x.DATE >= fromDate && x.DATE <= toDate)
on t1.NAME_ID equals t2.NAME_ID into t2_j
from t2s in t2_j.DefaultIfEmpty()
group t2s by t1.NAME into grouped
select new { Name = grouped.Key, Count = grouped.Sum(x => x.VALUE) }).
Where(x => x.Count.HasValue).
ToDictionary(o => o.Name,o => o.Count);
return dictionary;
}

Categories