LINQ query issue regarding Date - c#

I want to list out all records where CloseDate is greater than DateTime.Now.
I have write a query for that but it doesn't fetch records where CloseDate is greater than DateTime.Now.
See my query below
var query = (from x in objEntity.VacancyMsts
join o in objEntity.OrganizationMst on
x.OrganizationID equals o.OrganizationId into vacorg
from o in vacorg.DefaultIfEmpty()
where x.Status == true && x.CloseDate >= DateTime.Now
select new VacancyMstDTO
{});
Is there any problem in my query?

you dont need to join here if you have a FK relationship
var query = from x in objEntity.VacancyMsts
where x.Status && x.CloseDate >= DateTime.Now
select new VacancyMstDTO
{
OrganizationName = x.OrganizationMst.Name,
...
};
But I wonder if you really want the CloseDate to be ahead of today, normally a close date happens in the past, no?
And, careful with timezones as well. I tend to always insert/update the database with DateTime.UtcNow and when reading, apply the user timezone...

Related

MVC LINQ Not recognised method

I've got a linq query extracting data from a table and I want to, being given a Date, convert it to week ( for example what week of the year it is ).
And the GetWeekofYear function:
private int GetWeekOfYear(DateTime d)
{
var cal = System.Globalization.DateTimeFormatInfo.CurrentInfo.Calendar;
return cal.GetWeekOfYear(new DateTime(d.Year, d.Month, 1), System.Globalization.CalendarWeekRule.FirstDay, System.DayOfWeek.Sunday);
}
In its current state, when I'm trying to test it ( using Postman / Fiddler ) I am getting the following error:
LINQ to Entities does not recognize the method 'Int32
GetWeekOfYear(System.DateTime)' method, and this method cannot be
translated into a store expression
The error occurs because Linq2Sql can not translate the GetWeekOfYear method to SQL.
Try the following:
select raw data instead into QuestionaireDetailsDTO
select new QuestionaireDetailsDTO() {
DepartureDate = transport.DepartureDate
};
add a getter to QuestionaireDetailsDTO that does the calculation:
public string Week => GetWeekOfYear(DepartureDate);
This way the conversion happens in memory instead of on the DB.
If the GetWeekOfYear method resides in a project that is not accessible by the consumer of the DTO, add a postprocessing step instead after you have selected the DTOs from the DB.
foreach (var result in query) {
result.Week = GetWeekOfYear(result.DepartureDate);
}
You can do this by using .AsEnumerable()
var query = from booking in context.BookingTables
join transport in context.TransportAllotments on booking.TransportAllotmentID equals transport.TransportAllotmentID
join passenger in context.Passengers on booking.BookingID equals passenger.BookingID
join result in context.QuestionaireResults on passenger.PassengerID equals result.PassengerID
join question in context.QuestionaireQuestions on result.QuestionaireQuestionID equals question.QuestionaireQuestionID
where transport.DepartureDate >= startDate && transport.DepartureDate <= endDate && booking.BookingID == id
.AsEnumerable()
select new QuestionaireDetailsDTO()
{
ID = booking.BookingID,
Date = transport.DepartureDate,
Question = question.QuestionText,
Week = GetWeekOfYear(transport.DepartureDate)
};
Hope it help.
As meintoined, this happents because LinqToSQL wasnt able to translate your method to SQL.
I think that answer from #GeorgPatscheider is not a best because you shouldn't change your data objects because some specific mechanisms of data access layer.
So, answer from #PhongDao is more cool, but him solution will download too many fields from database. You can change your code this way:
var query = from booking in context.BookingTables
join transport in context.TransportAllotments on booking.TransportAllotmentID equals transport.TransportAllotmentID
join passenger in context.Passengers on booking.BookingID equals passenger.BookingID
join result in context.QuestionaireResults on passenger.PassengerID equals result.PassengerID
join question in context.QuestionaireQuestions on result.QuestionaireQuestionID equals question.QuestionaireQuestionID
where transport.DepartureDate >= startDate && transport.DepartureDate <= endDate && booking.BookingID == id
// select only fields which we need
select new
{
ID = booking.BookingID,
Date = transport.DepartureDate,
Question = question.QuestionText,
DepartureDate = transport.DepartureDate
}
// retrieve data from DB
.ToArray()
// create items which you need
.Select(x=>
new QuestionaireDetailsDTO()
{
ID = x.ID,
Date = x.Date,
Question = x.Question,
Week = GetWeekOfYear(x.DepartureDate)
})
// forming results
.ToArray();

Fetch records for past days excluding today using LinQ

I have database which consists of following columns:
App Icon, App Title, App Description, Date, Actual Price,
Itunes Link, AppID, UserID, Downloads Count
I need to know how many apps were inserted for past 7 days excluding today by Linq query. I tried goggling it and this is the code I found, but I am unable to modify it according to my needs
var q = from u in entity.Submit_App
where u.Date > DateTime.Now.AddDays(-30) &&
u.Date <= DateTime.Now
group u by EntityFunctions.TruncateTime(u.Date) into g
select new ChartTotal()
{
OrderDate = g.Key,
Total = g.Sum(y => y.GrandTotal)
};
Use DateTime.Today to get date without time part. Also you can introduce new range variable with let keyword to simplify your query:
var q = from u in entity.Submit_App
let date = EntityFunctions.TruncateTime(u.Date)
where date >= DateTime.Today.AddDays(-7) &&
date < DateTime.Today
group u by date into g
select new ChartTotal {
OrderDate = g.Key,
Total = g.Sum(x => x.GrandTotal)
};

Using Linq to SQL is it possible to retrieve two values and subtract them?

I am populating a class using Linq to SQL.
What I am trying to do is query my database, return two integer values and subtract the two values from each other, producing the result, but I can't think of a smart way to do it.
What can I do in this case ?
If it is not clear, , then this psuedocode implementation should clarify what functionality I wish for :
DECLARE #currentVal INT, #previousVal INT
#currentVal = SELECT VALUE
FROM Table1
WHERE Date = CURRDATE()
#previousVal = SELECT VALUE
FROM Table1
WHERE Date = MIN(Date)
RETURN #currentVal - #previousVal
But in Linq to SQL, (from o in context.Table1 where Date = currentDate select Value), how can I subtract the other value from this? Is this possible?
I'd stick to having it as a broken out set of queries, because you can then test if the values were actually returned or not and handle the case where too many values are returned:
var currentValResults = (from row in rows
where row.Date == DateTime.Now
select row.Value)
.ToArray();
var previousValResults = (from row in rows
let minDate = rows.Min(r => r.Date)
where row.Date == minDate
select row.Value)
.ToArray();
if (currentValResults.Length == 1 && previousValResults.Length == 1)
{
var diff = currentValResults[0] - previousValResults[0];
}
else
{
// Error condition?
}
Putting it all into a giant linq statement makes too many assumptions (or at least, my implementation does).
Why not simply do a cross join
var query=
from a in Table1 where a.Date == DateTime.Now
from b in Table1 where b.Date == Table1.Min(c=>c.Date)
select a.Amount - b.Amount;
var result=query.First();
Something like this would work to keep it into one trip to the db (Keep in mind this assumes that only two results will be returned):
int[] values = (from o in context.Table1
where Date = currentDate || Date = context.Table1.Min(x => x.Date)
order by Date descending
select value).ToArray();
return values[0] - values[1];
var currentVal = context.Table1.FirstOrDefault(t=>t.Date == DateTime.Now.Date);
var previousVal = context.Table1.FirstOrDefault(t=>t.Date == context.Table1.Min(d=>d.Date));
var result = currentVal - previousVal;
Or
from d in context.Table1
let prevVal = context.Table1.FirstOrDefault(t=>t.Date == context.Table1.Min(d=>d.Date));
where d.Date == DateTime.Now.Date
return new { d - prevVal };

Quick linq count question

I have the following query that returns the login count per day from a given date.
var sot = from uts in DataContext.UserTrackingStatistics
let startDate = new DateTime(2009, 10, 01)
where uts.LastLogin >= startDate
group uts by uts.LastLogin.Date into myGroup
orderby myGroup.Key.Date
select new { Count = myGroup.Count() , myGroup.Key.Date};
I would like this to say the count was 0 for a given day rather than not return anything. How could I do that within this query?
You can't do it just with LINQ-to-SQL, as you'd have to use a union on your query with data that doesn't actually exist, which LINQ-to-SQL can't do.
To do this, you'll need to fill in the gaps client-side. I'm not in front of VS at the moment, but a general approach would be this:
Define your date range (since you mention no end date in your code and we're talking about login date, I'm assuming that the end date would be the current date.
Use Enumerable.Range to create a list of numbers ranging from 0 to the number of days within your date range, then use Select to transform that list into a list of dates. Select your results using an anonymous type and use the same properties as your L2S statement; this way, the compiler will reuse the same type
Combine your lists together using an outer join (not the most obvious syntax in LINQ, unfortunately) on the Date property
Order your results by date
This will now show 0 for the gaps.
I'll try to post a code sample below, but note that I can't compile where I am, so it may require tweaking.
var allDates = Enumerable.Range(0, (DateTime.Today - startDate).TotalDays)
.Select(i => new { Count = 0, Date = startDate.AddDays(i) });
var fullResults = from d in allDates
join r in results on d.Date == r.Date
from oj in r.DefaultIfEmpty()
select new { Count = oj == null ? 0 : oj.Count, Date = d.Date };

Grouping by Time ranges in Linq

I've been getting stuck into some linq queries for the first time today and I'm struggling with some of the more complicated ones. I'm building a query to extract data from a table to build a graph. The tables colums I'm interested in are Id, Time and Value.
The user will select a start time, an end time and the number of intervals (points) to graph. The value column will averaged for each interval.
I can do this with a linq request for each interval but I'm trying to write it in one query so I only need to go to the database once.
So far I have got:
var timeSpan = endTime.Subtract(startTime);
var intervalInSeconds = timeSpan.TotalSeconds / intervals;
var wattList = (from t in _table
where t.Id == id
&& t.Time >= startTime
&& t.Time <= endTime
group t by intervalInSeconds // This is the bit I'm struggling with
into g
orderby g.Key
select g.Average(a => a.Value))
).ToList();
Any help on grouping over time ranges will be most welcome.
I've done this myself for exactly the same situation you describe.
For speed, modified the database's datapoints table to include an integer-based time column, SecondsSince2000, and then worked with that value in my LINQ to SQL query. SecondsSince2000 is a computed column defined as:
datediff(second, dateadd(month,1200,0), DataPointTimeColumn) PERSISTED
Where DataPointTimeColumn is the name of the column that stores the datapoint's time. The magic function call dateadd(month,1200,0) returns 2000-01-01 at midnight, so the column stores the number of seconds since that time.
The LINQ to SQL query is then made much simpler, and faster:
int timeSlotInSeconds = 60;
var wattList =
(from t in _table
where t.Id == id
&& t.Time >= startTime
&& t.Time <= endTime
group t by t.SecondsSince2000 - (t.SecondsSince2000 % timeSlotInSeconds)
into g
orderby g.Key
select g.Average(a => a.Value))).ToList();
If you can't modify your database, you can still do this:
var baseTime = new DateTime(2000, 1, 1);
var wattList =
(from t in _table
where t.Id == id
&& t.Time >= startTime
&& t.Time <= endTime
let secondsSince2000 = (int)(t.Time- baseTime).TotalSeconds
group t by secondsSince2000 - (secondsSince2000 % timeSlotInSeconds)
into g
orderby g.Key
select g.Average(a => a.Value))).ToList();
The query will be quite a bit slower.
Check out this example I wrote a while ago. It sounds like what you are trying to do, but I'm not sure if it does the grouping in SQL or by .NET.
http://mikeinmadison.wordpress.com/2008/03/12/datetimeround/
Maybe you can do something like:
var wattList = (from t in _table
where t.Id == id
&& t.Time >= startTime
&& t.Time <= endTime
).GroupBy(x => (int) ((x.Time - startTime).TotalSeconds / intervalInSeconds))
.Select(grp => grp.Average(x => x.Value));

Categories