Group the result using linq - c#

I have some problems and don't know what to do, can someone help me please?
I have a table like that:
ID Name Produkt Comment aa bb
1 Mike AA YY x
1 Mike AA YY x
I want to group with linq the result like to have Mike but just in one line
1 Mike AA YY x x
My code:
var results = from t1 in table.AsEnumerable()
join tb2 in table2.AsEnumerable()
on t1.Field<string>("Name") equals tb2.Field<string>("Name") into prodGroup
from table4 in prodGroup.DefaultIfEmpty()
select new
{
ID = t1.Field<Int32?>("ID"),
Name = t1.Field<String>("Name"),
Produkt = t1.Field<String>("Produkt"),
Attribute = t1.Field<String>("Attribute"),
Comment = table4 != null ? table4.Field<String>("Comment") : null,
};
foreach (var r in results)
{
var productIndex = result.Columns.IndexOf(r.Attribute);
var vals = new List<object>() { r.ID, r.Name, r.Produkt, r.Comment };
for (int i = 4; i < result.Columns.Count; i++)
{
if (i == productIndex)
{
vals.Add(true);
}
else
{
vals.Add(false);
}
}
result.LoadDataRow(vals.ToArray(), true);
}

Try this:
var result = from t1 in table.AsEnumerable()
group t1 by t1.Name into t1group
select new
{
Name = t1group.FirstOrDefault().Name
,ID = t1group.FirstOrDefault().ID
,Product = t1group.FirstOrDefault().Product
,Comment = t1group.FirstOrDefault().Comment
,aa = (t1group.Select(x => x.aa??"" + x.bb??"")).Aggregate((a, b) => (a + ", " + b))
};

Related

LINQ Group By Join

I'm struggling with what is a rather simple SQL select statement. How can this be translated into LINQ?
select
o.IdOrder, Date, s.suma, name, adresa
from
Clients c
join
Orders o on (c.IdClient = o.IdClient)
join
(select IdOrder, sum(price) suma
from OrderProduct
group by IdOrder) s on (o.IdOrder = s.IdOrder);
If you could point me in the right direction, I would greatly appreciate it.
This is what I have so far:
var y = from w in db.OrderProducts
group w by w.IdOrder into TotaledOrder
select new
{
IdOrder = TotaledOrder.Key,
price = TotaledOrder.Sum(s => s.price)
};
var i = 0;
var cc = new dynamic[100];
foreach (var item in y)
{
cc[i++] = db.Orders.Where(t => t.IdOrder == item.IdOrder)
.Select(p => new
{
IdOrder = item.IdOrder,
price = item.price,
}).Single();
}
Your SQL doesn't really give an idea on your underlying structure. By a guess on column names:
var result = from o in db.Orders
select new {
IDOrder = o.IDOrder,
Date = o.Date,
Suma = o.OrderProduct.Sum( op => op.Price),
Name = o.Client.Name,
Adresa = o.Client.Adresa
};
(I have no idea what you meant by the loop in your code.)

C# - LINQ - Sum a field from other table

I need to join two tables (Movimientos and Cuentas), group by CuentasId and make a SUM of Movimientos.Monto
Movimientos has a CuentasId to join this, and I can get the data from Cuentas but can not get the Sum.
This is my best approach, any help will be preciated, I'm a little confused with the syntax. Thanks in advance and kind regards,
var cuentas = (from mov in _data.Movimientos
join ct in _data.Cuentas
on mov.CuentasId equals ct.CuentasId
where ct.IsDeleted == 0 && mov.IsDeleted == 0
group ct by new
{
CuentasId = ct.CuentasId,
Alias = ct.Alias,
Moneda = ct.Monedas.Nombre,
Signo = ct.Monedas.Signo,
Banco = ct.Bancos.Nombre
} into ctg
select new
{
Alias = ctg.Key.Alias,
Moneda = ctg.Key.Moneda,
Signo = ctg.Key.Signo,
Banco = ctg.Key.Banco,
Monto = ctg.Sum(mov.Monto)
}
).ToList();
You need to group the value you want to sum like this
group mov.Monto by new { ..... } into ctg
Then ctg will be a collection of mov.Monto values grouped by your list of properties of ct and you'd just call Sum on ctg in your select
Monto = ctg.Sum()
So your new query would be
var cuentas = (from mov in _data.Movimientos
join ct in _data.Cuentas
on mov.CuentasId equals ct.CuentasId
where ct.IsDeleted == 0 && mov.IsDeleted == 0
group mov.Monto by new
{
CuentasId = ct.CuentasId,
Alias = ct.Alias,
Moneda = ct.Monedas.Nombre,
Signo = ct.Monedas.Signo,
Banco = ct.Bancos.Nombre
} into ctg
select new
{
Alias = ctg.Key.Alias,
Moneda = ctg.Key.Moneda,
Signo = ctg.Key.Signo,
Banco = ctg.Key.Banco,
Monto = ctg.Sum()
}).ToList();
You could also try grouping by first and then just summing the items later:
var cuentas = (from mov in _data.Movimientos.Where(w => w.IsDeleted == 0).GroupBy(g => g.CuentasId)
join ct in _data.Cuentas.Where(w => w.IsDeleted == 0).GroupBy(g => new { CuentasId = g.CuentasId, Alias = g.Alias, Monedas = g.Monedas.Nombre, Signo = g.Monedas.Signo, Banco = g.Bancos.Nombre })
on mov.Key.CuentasId equals ct.Key.CuentasId
select new
{
Alias = ct.Key.Alias,
Moneda = ct.Key.Moneda,
Signo = ct.Key.Signo,
Banco = ct.Key.Banco,
Monto = mov.Sum(s => s.Monto)
}
).ToList();

How to use LINQ to select the object with the smaller value of the property and its value directly

var req = (from k in dc.operations.ToList()
group k by k.id_employee into g
select new { id_emp = g.Key , nbr = g.Count(), }
).Take(1).SingleOrDefault();
double mint=0;
for (int i = 0; i < req.nbr; i++)
{
var r = (from l in dc.operations
where l.id_employee == req.id_emp
select l).Take(1).ToList();
var r2 = (from l in dc.operations
where l.id_employee == req.id_emp
&& l.date_operation.Value > r[i].date_operation.Value
select l).Take(1).ToList();
double nbr_minut = (r[i].date_operation.Value - r2[i].date_operation.Value).TotalMinutes;
mint = +nbr_minut;
nbr_minut = 0;
}
TimeSpan span = TimeSpan.FromMinutes(mint);
string nbr_houre = span.ToString(#"hh\:mm");
label1.Text = nbr_houre.ToString();
To simplify the question, lets say you have a list of Person and you want to get the youngest person and his age.
You can do this:
people.OrderBy(p => p.Age).Select(p => new {Dude = p, Age = p.Age}).FirstOrDefault();

How to convert SqlDataReader to LINQ way?

I wonder how to convert SqlDataReader to LINQ way?
Here is my SqlDataReader code.
string strConn = "server=xxx.com;database=mydb;User ID=test;Password=test;Trusted_Connection=true;";
SqlConnection myConn = new SqlConnection(strConn);
myConn.Open();
string strSQL = "select period from timetable_view where identity_num = '" + Identity_NUM + "' week = '3'";
SqlCommand myCommand = new SqlCommand(strSQL, myConn);
SqlDataReader myDataReader = myCommand.ExecuteReader();
int Count = Add_CourseConfirmedQuery.Count();
Random rnum = new Random();
string[] arr = new string[Count];
for (int i = 0; i < Count; i++)
{
myDataReader.Read();
arr[i] = myDataReader["period"].ToString();
}
ViewBag.test = arr[0];
ViewBag.test2 = arr[1];
myCommand.Cancel();
myDataReader.Close();
myConn.Close();
myConn.Dispose();
string[] input2 = new string[Count];
for (int i = 0; i < Count; i++)
{
input2[i] = arr[i];
}
This code works fine.
I've tried to code in LINQ but it doesn't work.
Here's the LINQ code that I've tried, but I have no idea how to extract all records of a.identity_num, and put them into an array like the code above(SqlDataReader).
var test = from a in timetable_view
where a.identity_num = Identity_NUM && a.week = "3"
select a new{a.identity_num};
ViewBag.test = test.FirstOrDefault();
[UPDATE Question]
This is what I am trying now.
I can't extract the right records from my table.
But the page display: System.String[]
var Query = from m in db.members
join d in db.departments on m.department equals d.department_id
join s in db.select_list on m.member_id equals s.member_id
join c in db.courses on s.kkk_id equals c.kkk_id
join t in db.teachers on c.teacher equals t.teacher_id
where m.identity_num == Identity_NUM && c.week == "3"
select c.period;
var PA = Query.ToArray();
int Count = Query.Count();
string[] arr = new string[Count];
for (int i = 0; i < Count; i++)
{
arr[i] = PA.ToString();
}
ViewBag.test = arr[0];
ViewBag.test2 = arr[1];
.............
............
...........
string[] input2 = new string[Count];
for (int i = 0; i < Count; i++)
{
input2[i] = arr[i];
}
.............
............
...........
Updated to match changed question:
Don't select a new anonymous object, just select the value:
var arr= (from a in timetable_view
where a.identity_num = Identity_NUM && a.week = "3"
select a.period).ToArray();
Fully updated change should be
var Query = from m in db.members
join d in db.departments on m.department equals d.department_id
join s in db.select_list on m.member_id equals s.member_id
join c in db.courses on s.kkk_id equals c.kkk_id
join t in db.teachers on c.teacher equals t.teacher_id
where m.identity_num == Identity_NUM && c.week == "3"
select c.period;
var arr = Query.ToArray();
ViewBag.test = arr[0];
ViewBag.test2 = arr[1];
From the comments:
The error message generated by having ToString() in the code indicates to us that period is a string anyhow and so the call can be removed.
To get count, int Count = arr.Length
The for-loop has been removed because it is redundant, using the ToArray() function achieves the same result.
you should need to convert linkq to toArray:
var TEST = (from a in timetable_view
where a.identity_num = Identity_NUM && a.week = "3"
select a new{a.identity_num}).ToArray();
var Query = from m in db.members
join d in db.departments on m.department equals d.department_id
join s in db.select_list on m.member_id equals s.member_id
join c in db.courses on s.kkk_id equals c.kkk_id
join t in db.teachers on c.teacher equals t.teacher_id
where m.identity_num == Identity_NUM && c.week == "3"
select c.period.ToString();
var arr = Query.ToArray();
ViewBag.test = arr[0];
ViewBag.test2 = arr[1];
You need to convert linq query to array. Bellow code should do this:
var test = (from a in school_timetable_view
where a.identity_num == Identity_NUM && a.week == "3"
select a new{a.identity_num}).ToArray();

Can a single LINQ Query Expression be framed in this scenario?

I am facing a scenario where I have to filter a single object based on many objects.
For sake of example, I have a Grocery object which comprises of both Fruit and Vegetable properties. Then I have the individual Fruit and Vegetable objects.
My objective is this:
var groceryList = from grocery in Grocery.ToList()
from fruit in Fruit.ToList()
from veggie in Vegetable.ToList()
where (grocery.fruitId = fruit.fruitId)
where (grocery.vegId = veggie.vegId)
select (grocery);
The problem I am facing is when Fruit and Vegetable objects are empty.
By empty, I mean their list count is 0 and I want to apply the filter only if the filter list is populated.
I am also NOT able to use something like since objects are null:
var groceryList = from grocery in Grocery.ToList()
from fruit in Fruit.ToList()
from veggie in Vegetable.ToList()
where (grocery.fruitId = fruit.fruitId || fruit.fruitId == String.Empty)
where (grocery.vegId = veggie.vegId || veggie.vegId == String.Empty)
select (grocery);
So, I intend to check for Fruit and Vegetable list count...and filter them as separate expressions on successively filtered Grocery objects.
But is there a way to still get the list in case of null objects in a single query expression?
I think the LINQ GroupJoin operator will help you here. It's similar to the TSQL LEFT OUTER JOIN
IEnumerable<Grocery> query = Grocery
if (Fruit != null)
{
query = query.Where(grocery =>
Fruit.Any(fruit => fruit.FruitId == grocery.FruitId));
}
if (Vegetable != null)
{
query = query.Where(grocery =>
Vegetable.Any(veggie => veggie.VegetableId == grocery.VegetableId));
}
List<Grocery> results = query.ToList();
Try something like the following:
var joined = grocery.Join(fruit, g => g.fruitId,
f => f.fruitId,
(g, f) => new Grocery() { /*set grocery properties*/ }).
Join(veggie, g => g.vegId,
v => v.vegId,
(g, v) => new Grocery() { /*set grocery properties*/ });
Where I have said set grocery properties you can set the properties of the grocery object from the g, f, v variables of the selector. Of interest will obviouly be setting g.fruitId = f.fruitId and g.vegeId = v.vegeId.
var groceryList =
from grocery in Grocery.ToList()
join fruit in Fruit.ToList()
on grocery.fruidId equals fruit.fruitId
into groceryFruits
join veggie in Vegetable.ToList()
on grocery.vegId equals veggie.vegId
into groceryVeggies
where ... // filter as needed
select new
{
Grocery = grocery,
GroceryFruits = groceryFruits,
GroceryVeggies = groceryVeggies
};
You have to use leftouter join (like TSQL) for this. below the query for the trick
private void test()
{
var grocery = new List<groceryy>() { new groceryy { fruitId = 1, vegid = 1, name = "s" }, new groceryy { fruitId = 2, vegid = 2, name = "a" }, new groceryy { fruitId = 3, vegid = 3, name = "h" } };
var fruit = new List<fruitt>() { new fruitt { fruitId = 1, fname = "s" }, new fruitt { fruitId = 2, fname = "a" } };
var veggie = new List<veggiee>() { new veggiee { vegid = 1, vname = "s" }, new veggiee { vegid = 2, vname = "a" } };
//var fruit= new List<fruitt>();
//var veggie = new List<veggiee>();
var result = from g in grocery
join f in fruit on g.fruitId equals f.fruitId into tempFruit
join v in veggie on g.vegid equals v.vegid into tempVegg
from joinedFruit in tempFruit.DefaultIfEmpty()
from joinedVegg in tempVegg.DefaultIfEmpty()
select new { g.fruitId, g.vegid, fname = ((joinedFruit == null) ? string.Empty : joinedFruit.fname), vname = ((joinedVegg == null) ? string.Empty : joinedVegg.vname) };
foreach (var outt in result)
Console.WriteLine(outt.fruitId + " " + outt.vegid + " " + outt.fname + " " + outt.vname);
}
public class groceryy
{
public int fruitId;
public int vegid;
public string name;
}
public class fruitt
{
public int fruitId;
public string fname;
}
public class veggiee
{
public int vegid;
public string vname;
}
EDIT:
this is the sample result
1 1 s s
2 2 a a
3 3

Categories