C# Entity Framework Group Count - c#

Currently working on getting data into some sort of array for a DotNet.Highcharts chart. I have a problem with getting the data out of my database. Entity framework is giving me the following error:
DbExpressionBinding requires an input expression with a collection ResultType.
select t.code, type, count(type)
from tbl_data d
join tbl_code t on d.code_name = t.code_id
where type is not null
group by code, type
order by code
using (Context db = new Context())
{
var data = db.tbl_data
.Where(d => d.type != null)
.GroupBy(d => new { d.tbl_code.code, d.type })
.Select(d => new { name = d.Key.code, type = d.Key.type , count = d.Key.type.Count() })
.OrderBy(d => new { d.name, d.type });
List<string> x_Axis = new List<string>();
List<object[]> y_Axis = new List<object[]>();
foreach (var d in data)
{
x_Axis.Add(d.name);
y_Axis.Add(new object[] { d.type, d.count });
}
var xArray = x_Axis.ToArray();
render_Chart(xArray, y_Axis);
}
A sample of the data from SQL is below.
code type (No column name)
eis06 a 49
eis06 b 3
eis07 a 33
eis08 a 38
eis09 a 32
eis09 b 68
eis14 a 17
eis14 b 34
eis15 a 24
eis15 b 17
eis16 a 27
eis16 b 16
Edited because the initial problem was trivial, this new problem is blocking me now.

Related

Select n rows randomly everyday in LINQ

I am new in C# and have a quick question about the LINQ. I have a database which has two tables Re and De. The Re table has "Time" and "Id" columns. De table has "Id" and "data" columns. Now I want to get 5 entries from Re everyday and these 5 entries have to be randomly selected by time within that day. How can I do that. In addition, is there any kind of random number seed such that I can reproduce the randomness ? I tried couple of times, but it doesn't work.
Here is my code:
using (var db = new DBContext("Name=MyDB"))
{
var Query = db.Re.Join(db.De,
r => r.Id,
d => d.Id,
(r, d) => new { r, d })
.Where(cr => cr.r.Time >= new DateTime(2016, 1, 1)
&& cr.r.Time < new DateTime(2016, 1, 30))
.OrderByDescending(cr => cr.r.Id)
.GroupBy(a => new { y = a.r.Time.Year,
m = a.r.Time.Month,
d = a.r.Time.Day })
.SelectMany(g=>g.OrderBy(row => Guid.newGuid()).Take(200))
.Select(e => new
{
myId = e.r.Id,
mydata = e.d.data
})
.Take(100);
}

How to get data between two columns in datatable?

If i have two data tables like this :
1-penaltyrule
ser from-min to-min pen
1 1 55 1
2 56 90 2
3 91 null 3
2- penaltyEmp
ser emp tot-min
1 782 2
2 672 67
3 677 92
4 56 7
I want to get the pen for each user with LINQ
i mean where tot-min BETWEEN from-min AND to-min SELECT
pen
I want data table with the following result :
emp pen
782 1
672 2
677 3
56 1
You can use this query:
var penaltyEmps = penaltyEmp.AsEnumerable()
.Select(r => new { ser = r.Field<int>("ser"), emp=r.Field<int>("emp"), tot_min=r.Field<int>("tot-min"), row = r });
var penaltyrules = penaltyrule.AsEnumerable()
.Select(r => new { ser = r.Field<int>("ser"), from_min=r.Field<int>("from-min"), to_min=r.Field<int>("to-min"), row = r });
DataTable tblResult = penaltyEmps
.Select(x => new
{
penaltyEmp = x,
matchingRules = penaltyrules.Where(x2 => x.tot_min >= x2.from_min && x.tot_min <= x2.to_min)
})
.Where(x => x.matchingRules.Any())
.Select(x => x.penaltyEmp.row)
.CopyToDataTable();
Something like this should work in LINQ for you: (Don't forget to include the System.Linq namespace).
var results = from emp in context.penaltyEmp
join rule in context.penaltyRule on emp.ser equals rule.ser
where emp.tot-min > rule.from-min && emp.tot-min < rule.to-min
select new { emp = emp.emp, pen = rule.pen };
you can use this if you are using EF
var data=(from a in db.penaltyEmp
select new{
emp= a.emp,
pen= db.penaltyrule.Where(d=>d.from-min>a.tot-min && d.to-min==null?true:(d.to-min>a.tot-min)).Select(d=>d.pen).firstOrDefault()
});

Difference between value of first and last record Linq [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have data in my List as below
profilename date score
prof1 01/10/2015 15
prof1 02/10/2015 15
prof1 03/10/2015 18
....
prof1 25/10/2015 24
prof2 01/10/2015 69
prof2 02/10/2015 70
prof3 01/10/2015 115
prof3 02/10/2015 115
prof2 03/10/2015 73
prof3 03/10/2015 119
....
prof2 25/10/2015 98
prof3 25/10/2015 187
I want to calculate the difference of score between the first and last record by date of each profilename. Required output is
prof1 9
prof2 29
prof3 72
I have no idea how to start out this query in Linq as I am new to it. Any help would be appreciated.
I want to calculate the difference of score between the first and last record by date of each profilename.
So you need to group by profilename, sort each group by date, take the first and last item and calculate the difference
var result =
(from item in list
group item by item.profilename into g
let groupItems = g.OrderBy(gi => Convert.ToDateTime(gi.date))
select new { profilename = g.Key, score = groupItems.Last().score - groupItems.First().score }
).ToList();
You can group by profilename and calc difference like:
var result = list.GroupBy(c => c.profilename).
Select(c => new
{
profilename = c.Key,
score = c.FirstOrDefault(m => m.date == c.Max(v => v.date)).score -
c.FirstOrDefault(m => m.date == c.Min(v => v.date)).score
}).ToList();
If it's Linq-To-Sql as mentioned in the comment this is probably the best approach:
var result = profiles
.GroupBy(p => p.profilename)
.Select(g => new {
profilename = g.Key,
firstscore = g.OrderBy(p => p.date).First().score,
lastscore = g.OrderByDescending(p => p.date).First().score
})
.Select(x => new { x.profilename, diff = x.lastscore - x.firstscore })
.ToList();
Demo fiddle
Not the best performance, but if you care about performance just don't use LINQ
.GroupBy(e => e.Group).Select(e => new KeyValuePair<string, int>(e.Key, e.OrderBy(f => f.Date).Last().Num - e.OrderBy(f => f.Date).First().Num)).ToList();
This seems to work (full code below, using DateTime):
var l = list.OrderBy(i => i.date)
.GroupBy(i => i.profileName)
.Select(e => new {prof = e.First().profileName, diff = e.Last().score - e.First().score}).ToList();
Here's a compilable example including your data:
class Rate
{
public Rate(string p, string d, int s)
{
profileName = p;
date = DateTime.Parse(d);
score = s;
}
public string profileName;
public DateTime date;
public int score;
}
void Main()
{
var list = new List<Rate>()
{
new Rate("prof1", "01/10/2015", 15),
new Rate("prof1", "02/10/2015", 15),
new Rate("prof1", "03/10/2015", 18),
new Rate("prof1", "25/10/2015", 24),
new Rate("prof2", "01/10/2015", 69),
new Rate("prof2", "02/10/2015", 70),
new Rate("prof3", "01/10/2015", 115),
new Rate("prof3", "02/10/2015", 115),
new Rate("prof2", "03/10/2015", 73),
new Rate("prof3", "03/10/2015", 119),
new Rate("prof2", "25/10/2015", 98),
new Rate("prof3", "25/10/2015", 184),
};
var l = list.OrderBy(i => i.date)
.GroupBy(i => i.profileName)
.Select(e => new {prof = e.First().profileName, diff = e.Last().score - e.First().score}).ToList();
}

c# collection manipulation with Linq

I have a collection in this format
IList<ReportRow> MyCollection
Where ReportRow is a
Dictionary<string, object>
So MyCollection might look like this:
Id1 Id2 Value Status Entered
123 2 56 New 50:01.7
123 2 76 Old 50:23.0
123 2 12 New 50:23.0
127 3 54 Old 50:23.0
127 3 77 New 59:23.0
...
Is there a way in Linq that I can do this:
What I need to do is for each Id1+Id2 combination I need to output the Value where Status is New and where the status is Old. There might be multiple New values for an Id1+Id2 combination so it should pick up the latest New record, using the Entered column to sort.
The new record will contain all the records plus 1 extra column like so:
Id1 Id2 NewValue OldValue Entered
123 2 12 76 50:23.0
127 3 77 54 59:23.0
Any help with this would be great
This should do it (or be close as this is off the top of my head)
collection.OrderByDescending(r => r.Value.Entered)
.GroupBy(r => {r.Id1, r.Id2)
.Select(g => new {
Id1 = g.Key.Id1,
Id2 = g.Key.Id2,
NewValue = g.FirstOrDefault(v => v.Status == "New").Value ?? 0,
OldValue = g.FirstOrDefault(v => v.Status == "Old").Value ?? 0,
Entered = g.Last().Entered
})
If you don't care for the dictionary string key you could do
collection.SelectMany(d => d.Value)
.OrderByDescending(r => r.Value.Entered)
.GroupBy(rr => {rr.Value.Id1, rr.Value.Id2)
.Select(g => new {
Id1 = g.Key.Id1,
Id2 = g.Key.Id2,
NewValue = g.FirstOrDefault(v => v.Status == "New").Value ?? 0,
OldValue = g.FirstOrDefault(v => v.Status == "Old").Value ?? 0,
Entered = g.Last().Entered
})
from row in MyCollection
group row by new { row.Id1, row.Id2 } into g
let lastNew = g.OrderByDescending(r => r.Entered)
.FirstOrDefault(r => r.Status == "New")
let lastOld = g.OrderByDescending(r => r.Entered)
.FirstOrDefault(r => r.Status == "Old")
select new {
Id1 = g.Key.Id1,
Id2 = g.Key.Id2,
NewValue = (lastNew == null) ? null : (int?)lastNew.Value,
OldValue = (lastOld == null) ? null : (int?)lastOld.Value,
Entered = g.OrderByDescending(r => r.Entered).First().Entered
}

How to find same values in a list column and concatenating strings on the other rows for the same column value

I have a List with 2 columns with the following structure:
50 process:3333
50 phone:xxxx
51 process:2222
51 phone:yyyy
I need to build a new list based on that first one with this structure:
50 process:3333,phone:xxxx
51 process:2222,phone:yyyy
Does List have any method to find from one column a same value and concatenate the string on second column.
Or I have to find a way to do it manually using a foreach or a while statement?
Assuming a simple struct like...
public struct Proc
{
public int ID { get; set; }
public string Value { get; set; }
}
with your sample data:
var procList = new List<Proc>() {
new Proc{ID=50,Value="process:3333"},new Proc{ID=50,Value="phone:xxxx"},
new Proc{ID=51,Value="process:2222"},new Proc{ID=51,Value="phone:yyyy"},
};
You can use Enumerable.GroupBy and String.Join:
var procIdGroupList = procList
.GroupBy(p => p.ID)
.Select(g => new Proc
{
ID = g.Key,
Value = string.Join(",", g.Select(p => p.Value))
}).ToList();
DEMO
Found a workaround for that:
//Recupera valores dos indices para o tipo de documento
List<Gedi.Models.OperacoesModel.imports> valuesList = new List<Gedi.Models.OperacoesModel.imports>();
var valuesListObj = from a in context.sistema_Documentos
join b in context.sistema_Indexacao on a.id equals b.idDocumento
join c in context.sistema_Indexes on b.idIndice equals c.id
where a.ativo == 1
select new
{
id = a.id,
values = c.idName + ":" + b.valor
};
var çist = (from x in valuesListObj.AsEnumerable()
select new Gedi.Models.OperacoesModel.imports
{
id = x.id,
values = x.values
}).ToList();
var importList = çist.GroupBy(p => p.id).Select(g => new Gedi.Models.OperacoesModel.imports
{
id = g.Key,
values = string.Join(",", g.Select(p => p.values))
}).ToList();

Categories

Resources