How to summarize DateTime-fields in EF6 - entity-framework

again, I'm struggeling with Linq or EF6.
I have a table with columns (DateTime)[BeginOfWork] and (DateTime)[EndOfWork].
Now, I need to substract the BeginOfWork-value from the EndOfWork-value. From this result, I need to build a total sum.
In SQL, it looks like this:
SELECT Timesheets.EmployeeId, Sum(DateDiff("h",[Timesheets].[BeginOfWork],[Timesheets].[EndOfWork])) AS HoursOfWork
FROM Timesheets
GROUP BY Timesheets.EmployeeId
HAVING (((Timesheets.EmployeeId)=1));
How do I do this in EF6?
Actually, not working some variations of that:
int employeeId = 1;
var timesheetSum = (from ts in db.Timesheets
where (ts.EmployeeId == employeeId)
select new
{
hoursOfWork = DbFunctions.DiffHours(ts.BeginOfWork, ts.EndOfWork)
}).Sum(ts => ts.hoursOfWork);
The above results in integer rounded hoursOfWork, that don't include minutes.
So I tried that:
var timesheetSum = (from ts in db.Timesheets
where (ts.EmployeeId == employeeId)
select new
{
hoursOfWork = DbFunctions.DiffMinutes(ts.BeginOfWork, ts.EndOfWork) / 60
}).Sum(ts => ts.hoursOfWork);
But here, hoursOfWork seems to be rounded (integer), so 2,5 hours will result in 2. Perhaps a conversion of the result would work but I don't get it run.
`(double)hoursOfWork` results in an error.
Perhaps someone has a link to a complete guide, how to convert SQL to Linq-queries.
SOLUTION
var timesheetSum = (from ts in db.Timesheets
where (ts.EmployeeId == employeeId && ts.TimesheetDate <= DateTime.Today)
select new
{
hoursOfWork = DbFunctions.DiffMinutes(ts.BeginOfWork, ts.EndOfWork)/60m
}).Sum(ts => ts.hoursOfWork);
decimal result = 0;
if(timesheetSum!=null)
result = (decimal)timesheetSum;
Thanks a lot
Carsten

Related

Easiest way to delete all records except the last 10 by date using EFCore [duplicate]

Let's say that I have a table like:
Id Name Category CreatedDate
1 test test 10-10-2015
2 test1 test1 10-10-2015
...
Now, I would like to delete all rows and leave only the top 10 from all categories (by top 10 I mean the 10 newest according to createdDate).
Using raw SQL, it would be like:
DELETE FROM [Product]
WHERE id NOT IN
(
SELECT id FROM
(
SELECT id, RANK() OVER(PARTITION BY Category ORDER BY createdDate DESC) num
FROM [Product]
) X
WHERE num <= 10
How is this done when using the DbContext in Entity Framework?
// GET all products
var list = ctx.Products.ToList();
// GROUP by category, ORDER by date descending, SKIP 10 rows by category
var groupByListToRemove = list.GroupBy(x => x.Category)
.Select(x => x.OrderByDescending(y => y.CreatedDate)
.Skip(10).ToList());
// SELECT all data to remove
var listToRemove = groupByListToRemove.SelectMany(x => x);
// Have fun!
ctx.Products.RemoveRange(listToRemove);
Guessing it will take a whil if you have a lot of data but.
var oldItems = efContext.Products
.GroupBy(x => x.Category,
(c,p) => p.OrderByDescending(x => p.createdDate).Skip(10))
.SelectMany(p => p);
efContext.Products.RemoveRange(oldItems);
Will do the trick
(Written in notepad)

Entity Framework equivalent of datepart(qq, getdate)

I have the following SQL query which I want to translate to EF query
Select Year(_r.IssueDate) as Year, datepart(qq, _r.IssueDate) as Quarter,count(*) as TotalBillableRecords, SUM(_r.BillableHours) as TotalHOurs
FROM
(select _b.Name, _i.IssueDate, _ie.BillableHours from Beneficiaries _b
join [Beneficiaries.Invoices] _i on _b.Id = _i.BeneficiaryId
join [Beneficiaries.Invoices.Entries] _ie on _ie.InvoiceId = _i.Id
where BeneficiaryId = 1) as _r
group by Year(_r.IssueDate), datepart(qq, _r.IssueDate)
This results in this
And this is what I would also want to have in my linq expression
How can I translate this to EF query ? I've tried like so
var query =
from beneficiary in _dbContext.Beneficiaries
where beneficiary.Id == beneficiaryId
from invoice in beneficiary.Invoices
//where invoice.IssueDate >= since
//where invoice.IssueDate.Month > notBefore && invoice.IssueDate.Month <= notAfter
from invoiceEntry in invoice.InvoiceEntries
group new
{
beneficiary,
invoiceEntry,
}
by new
{
Year = beneficiary.InvoiceMeta.IssueDate.Year,
Quarter = (beneficiary.InvoiceMeta.IssueDate.Month - 1) / 3 + 1,
}
into #group
select new
{
Year = #group.Key.Year,
Quarter = #group.Key.Quarter,
Hours = #group.Sum(x => x.invoiceEntry.BillableHours),
};
var y = query.ToList();
But the result is as following
[0] = Quarter = 3, Year = 2022, Hours = 6729.0
And this is it, only one entry.
What I'm noticing is that it only takes the last quarter composed of 3 months, (because the last would be the one which is not finished yet)
The class hierarchy is
Beneficiary 1-* Invoice 1-* Entries

Entity Framework Core Count unrelated records in another table

I need to count how many records in the tableA are not in the tableA, how to do this with LINQ?
with SQL I do the following way
select count(*) as total from produtoitemgrade g
where g.id not in (select idprodutograde from produtoestoque where idProduto = 12)
and g.idProduto = 12
my linq code so far.
var temp = (from a in Produtoitemgrades
join b in Produtoestoques on a.IdUnico equals b.IdUnicoGrade into g1
where g1.Count(y => y.IdProduto == 12)>0 && !g1.Any()
select a).ToList();
I tried to follow that example LINQ get rows from a table that don't exist in another table when using group by?
but an error occurs when running, how can I do this?
Thanks!
Your query should looks like the following, if you want to have the same SQL execution plan:
var query =
from a in Produtoitemgrades
where !Produtoestoques.Where(b => a.IdUnico == b.IdUnicoGrade && b.idProduto == 12).Any()
&& a.idProduto == 12
select a;
var result = query.Count();

EF 6.0 Get by datetime

I want to read from the table by datetime. If I use this:
(from x in Db.Table where x.Date.Value == DateTime.Now select x).ToList();
my code throws EntityCommandExecutionException:
A failure occurred while giving parameter information to OLE DB
provider
So I use this:
(from x in Db.Table where DbFunctions.TruncateTime(x.Date) == DateTime.Now select x).ToList();
but it is very slowly (about 40 seconds). In my table is approximately 500 000 records.
Thanks for advice
define now property first and then query like following:
var now = DateTime.Now;
var list = Db.Table.Where(e=>e.Date == now).ToList();
Or:
(from x in Db.Table where x.Date == now select x).ToList();

EF6 query with Max and filters

In C# code with EF6 and Sql Server, my goal is to use this query :
Select MAX(columnA) from myTable WHERE columnB>5 AND ColumnC=1
by using C# code.
Example :
SELECT Max(ColumnA) from myTable
becomes :
int max = DbContext.myTable.Max(t => t.ColumnA); => works fine, OK
But do you know how to add the where clause into this C# code ???
Erixx
You put Where first and then Max later like this
int max = DbContext.myTable.Where(it=>it.columnB>5 && it.ColumnC=1).Max(t => t.ColumnA);
Just add the Where before Max (or after, depending on your logic).
int max = DbContext.myTable.Where(t => t.ColumnB > 5 && ColumnC == 1).Max(t => t.ColumnA)