today's records fetching from linq to sql - asp.net-mvc-3

i want to fetch records of todays from my table.
I written following query -
public ICollection<DashboardNotification> GetNotificationOfToday()
{
DateTime todaysDate = DateTime.Now;
DateTime yesterdaysDate = DateTime.Now.AddDays(-1);
db = new BobTheBuilderEntities();
var notificationList = (from n in db.DashboardNotifications.OrderByDescending(n => n.NotificationDateTime)
where (n.NotificationDateTime > yesterdaysDate && n.NotificationDateTime <= todaysDate)
select n).ToList();
return notificationList;
}
But above query is not working, cause it fetching records from yesterday too.
How to resolve this problem ?

Try the following query
var notificationList = (from n in db.DashboardNotifications.OrderByDescending(n => n.NotificationDateTime)
where (n.NotificationDateTime > yesterdaysDate )
select n).ToList();

Can you pls try declaring yesterdays date as a variable first
var yesterDay = DateTime.Now.AddDays(-1);
var notificationList = (from n in db.DashboardNotifications.OrderByDescending(n => n.NotificationDateTime)
where (n.NotificationDateTime > yesterDay)
select n).ToList();

Related

Limiting a query to the rows created today (Linq-to-Entities, Datetime)

So I've got this query:
var query = from r in context.Cars
let h = context.CarHistories
.Where(u => r.ID == u.CarID)
.Where(u => u.EventID == intEventID)
.OrderByDescending(u => u.CreatedDate)
.FirstOrDefault()
select new RefundListItem()
{
ID = r.ID,
VendorID = r.VendorID,
RecipientName = r.RecipientName,
MostRecentSubmittedName = h.CreatedName,
CreatedDate = h.CreatedDate,
};
Later on, I add this to the query because I only want the rows that were created today:
DateTime today = DateTime.Today;
query.Where(u => Convert.ToDateTime(u.CreatedDate) >= today);
For some reason, this where statement does not affect the query at all. The query still returns items created from previous days instead of limiting them to just the rows created today.
I have also tried this but it does not work either:
DateTime today = DateTime.Today.Date;
query.Where(u => Convert.ToDateTime(u.CreatedDate.Date) >= today.Date);
I'm using Linq-to-Entities (MVC 4, EF 4).
Where does not modify query instance, it returns new one with additional condition added. Assign it back to query to make it work:
query = query.Where(u => Convert.ToDateTime(u.CreatedDate.Date) >= today.Date);

Using case statement in linq query

I have a linq query like this :
var trfplanList = (from at in entities.tdp_ProviderAccomodationType
join ap in entities.tdp_ProviderAccomodationTariffPlan on at.PATID equals ap.FK_PATID
join ac in entities.tdp_ProviderAccomodationCategory on ap.FK_PACID equals ac.PACID
where at.FK_ProviderID == CityID && at.IsApproved == 0 && ap.IsApproved == 0 && ac.AccomodationCategory == "Double Occupy"
orderby at.AccomodationType,ap.FromDate,ap.SType
select new AccomodationTariff
{
AccomodationType = at.AccomodationType,
SType = ap.SType,
FromDate = Convert.ToDateTime(ap.FromDate),
ToDate = Convert.ToDateTime(ap.ToDate),
RoomTariff = Convert.ToDecimal(ap.Rate),
ExPAXRate = Convert.ToDecimal(at.PerPaxRate)
}).ToList();
I have two questions:
Can't I convert value while assigning in the select new {} block ? it is giving me an error in project.
I want use 'case' while selecting ExPAXRate from the database for example in SQL I used to write :
CASE ap.SType WHEN 'Off Season' THEN at.PerPaxRateOS ELSE at.PerPaxRate END AS ExPAXRate
Can I use something like this in linq query ?
Can't I convert value while assigning in the select new {} block
No, you can't (sadly). EF doesn't know how to translate it into SQL.
I want use 'case'
You can use the ternary operator (?):
ExPAXRate = at.OffSeason ? at.PerPaxRateOS : at.PerPaxRate
(assuming that at.OffSeason exists).
A solution for the conversion issue could be to project into an anonymous type first and then, in memory, to AccomodationTariff:
...
select new
{
AccomodationType = at.AccomodationType,
SType = ap.SType,
FromDate = ap.FromDate,
ToDate = ap.ToDate,
RoomTariff = ap.Rate,
ExPAXRate = at.PerPaxRate
}).AsEnumerable()
.Select(x => new AccomodationTariff
{
AccomodationType = x.AccomodationType,
SType = x.SType,
FromDate = Convert.ToDateTime(x.FromDate),
ToDate = Convert.ToDateTime(x.ToDate),
RoomTariff = Convert.ToDecimal(x.Rate),
ExPAXRate = Convert.ToDecimal(x.PerPaxRate)
}).ToList();

How to get all the birthdays of today?

Does anyone know how to make a Linq query that gets all the birthdays of today? The code below doesn't work :
var getBirthdays =
orgContext.CreateQuery<Contact>()
.Where(c => c.BirthDate != null
&& c.BirthDate.Value.Month == DateTime.Now.Month).ToList();
I get an error like this:
"Invalid 'where' condition. An entity member is invoking an invalid
property or method."
Thanks in advance!
Anytime a vendor writes a four part blog series on how to do something as simple as finding a birthday (as Microsoft did in 2007), you have to know this won't be simple. So far as I can tell, this hasn't updated since then.
Find contacts with upcoming birthdays
Find contacts with upcoming birthdays - Part 2
Find contacts with upcoming birthdays - Parts 3 and 4
So you have limited options:
Make new fields called something like new_birthmonth and new_birthday that's updated every time a contact is created or updated via a plugin, and then query on those int fields.
Using Dynamic Linq, construct an OR clause in your WHERE clause that checks to see if the birthday falls in a reasonable range of years (say, 140 for the long-livers) (code below).
List<string> birthdays = new List<string>(); //will contain list of OR clauses
//makes sure no CRM unsupported dates are passed (less than 1/1/1900)
for (int i = Math.Min(140, DateTime.Today.Year - 1900); i > -1; i--)
{
//adds a different date per year
birthdays.Add
(
string.Format
(
//DateTimes are stored in UTC
"BirthDate = DateTime.Parse(\"{0}\")",
DateTime.Today.ToUniversalTime().AddYears(-i)
)
);
}
//completes the correct dynamic linq OR clause
string birthdayList = string.Join(" OR ", birthdays);
var getBirthdays = orgContext.CreateQuery<Xrm.Contact>()
.Where(c => c.BirthDate != null)
.Where(birthdayList)
.ToList();
I solved my problem based on the example of "Peter Majeed" and using "LinqKit"!
var predicate = PredicateBuilder.False<Contact>();
for (int i = Math.Min(140, DateTime.Today.Year - 1900); i > -1; i--)
{
DateTime cleanDateTime = new DateTime(DateTime.Today.AddYears(-i).Year, DateTime.Today.AddYears(-1).Month, DateTime.Today.AddYears(-i).Day);
predicate = predicate.Or(p => p.BirthDate == cleanDateTime.ToUniversalTime());
}
var getBirthdays = (from c in orgContext.CreateQuery<Contact>().AsExpandable().Where(predicate)
select c).ToList();
The above query gave me the correct result! Thx to all who helped me!
If c.BirthDate is nullable, you have to convert it to a datetime first:
var getBirthdays = orgContext.CreateQuery<Contact>()
.Where(c => c.BirthDate != null &&
(Convert.ToDateTime(c.BirthDate).Month ==
DateTime.Now.Month) &&
Convert.ToDateTime(c.BirthDate).Day ==
DateTime.Now.Day))
.ToList();
You could fetch this info with a Query, if that is possible in your situation?
//set up the condition + filter
var ce = new Microsoft.Xrm.Sdk.Query.ConditionExpression();
ce.Operator = Microsoft.Xrm.Sdk.Query.ConditionOperator.LastXDays;
ce.AttributeName = "birthdate";
ce.Values.Add(30);
var fe = new Microsoft.Xrm.Sdk.Query.FilterExpression();
fe.AddCondition(ce);
//build query
var query = new Microsoft.Xrm.Sdk.Query.QueryExpression();
query.EntityName = "contact";
query.Criteria.AddFilter(fe);
//get results
var results = CrmHelperV5.OrgProxy.RetrieveMultiple(query);
//if you want early bound entities, convert here.
var contacts = new List<Contact>();
foreach(var result in results.Entities)
{
contacts.Add(result.ToEntity<Contact>());
}
You may want to investigate the other operators for the filters + conditions
You can use QueryExpression (it works for Microsoft CRM Plugin)
public EntityCollection getBirthdateList(IOrganizationService orgsService)
{
List<string> birthdays = new List<string>();
//makes sure no CRM unsupported dates are passed (less than 1/1/1900)
for (int i = Math.Min(140, DateTime.Today.Year - 1930); i > -1; i--)
{
//adds a different date per year
birthdays.Add
(
DateTime.Now.AddYears(-i).ToString("yyyy-MM-dd")
);
}
// Instantiate QueryExpression
var query = new QueryExpression("contact");
// Define filter QEquote.Criteria
var queryfilter = new FilterExpression();
query.Criteria.AddFilter(queryfilter);
// Define filter
queryfilter.FilterOperator = LogicalOperator.Or;
queryfilter.AddCondition("birthdate",ConditionOperator.In,birthdays.ToArray());
return orgsService.RetrieveMultiple(query); ;
}

In Linq2SQL, how do I get a record plus the previous and next in the sequence in a single query?

Given a date, what is the most efficient way to query the last record before that date, any record that equals that date, and the next one after that date.
It should be functionally equivalent to a query like this:
from asset in Assets
where asset.Id == assetId
select new {
Previous = (from a in a.Orders where a.Date < myDate orderby a.Date descending select a).FirstOrDefault(),
Current = (from a in a.Orders where a.Date == myDate select a).SingleOrDefault(),
Next = (from a in a.Orders where a.Date > myDate orderby a.Date select a).FirstOrDefault()
}
As is, this query runs three queries, and presumably has to sort the dataset by myDate three times to do it.
Some similar questions:
How do I get 5 records before AND after a record with a specific ID? (just uses two queries)
How do I get records before and after given one? Not in Linq, and therefore hard for me to take advantage of (my team will get annoyed).
To provide the "most efficient" query depends on what you mean by efficient.
If you want a single query to the database, a single sort of orders by date and finally fast look-ups by date then I suggest the following might be the most efficient. :-)
var orders =
(from a in Assets
where a.Id == assetId
from o in a.Orders
orderby o.Date
select o).ToArray();
var previous = orders.LastOrDefault(o => o.Date < myDate);
var current = orders.SingleOrDefault(o => o.Date == myDate);
var next = orders.FirstOrDefault(o => o.Date > myDate);
This should query the database once for the orders associated with the required asset Id, sort them by date, and return them as an array in memory. Since this is in memory it is now blindingly fast to look for the current, previous & next records for the specified date.
Does your Orders table have a sequential ID field? If so, you might be able to do it with:
from asset in Assets
where asset.Id == assetID
let current = asset.Orders.Where(x => x.Date == myDate).FirstOrDefault()
where current != null
let previous = asset.Orders.Where(x => x.id == current.id - 1).FirstOrDefault()
let next = asset.Orders.Where(x => x.id == current.id + 1).FirstOrDefault()
select new {
Previous = previous,
Current = current,
Next = next
};
If it doesn't, then it'd be a bit more code:
from asset in Assets
where asset.Id == assetID
let current = asset.Orders.Where(x => x.Date == myDate).FirstOrDefault()
where current != null
let previous = asset.Orders.Where(x => x.Date < current.Date).OrderByDescending(x => x.Date).FirstOrDefault()
let next = asset.Orders.Where(x => x.Date > current.Date).OrderBy(x => x.Date).FirstOrDefault()
select new {
Previous = previous,
Current = current,
Next = next
};
That should get compiled into a single SQL query that utilizes sub-queries. IE: the database server will execute multiple queries, but your client program is only submitting one.
Edit One other idea that would work if your Order table had sequential IDs:
var sample = (from asset in Assets
where asset.Id == assetID
let current = asset.Orders.Where(x => x.Date == myDate).FirstOrDefault()
where current != null
from order in asset.Orders
where order.Id == current.id - 1
select order)
.Take(3)
.ToArray();
var Previous = sample[0];
var Current = sample[1];
var Next = sample[2];
Other Answers, for example, SkipWhile etc. very very slow. Good luck ^^
//Current Record
var query
= (from item in db.Employee
where item.UserName.Equals(_username)
select item).SingleOrDefault();
//Next Record
var query
= (from item in db.Employee
where item.UserName.CompareTo(_username) > 0
select item).FirstOrDefault();
//Previous Record
var query
= (from item in db.Employee
where item.UserName.CompareTo(_username) < 0
orderby item.UserName Descending
select item).FirstOrDefault();
Almost the same, but the SQL query plan might be different.
var q =
from asset in Assets
where asset.Id == assetID
select new
{
Previous = asset.Orders.where(a => a.Date == asset.Orders.Where(x => x.Date < myDate).Max(x => x.Date)).FirstOrDefault(),
Current = asset.Orders.Where(x => x.Date == myDate).FirstOrDefault(),
Next = asset.Orders.where(a => a.Date == asset.Orders.Where(x => x.Date > myDate).Min(x => x.Date)).FirstOrDefault()
};

date difference with linq

With this code:
i.SpesaAlloggio = db.TDP_NotaSpeseSezB.Sum(p => p.Costo / (((DateTime)p.DayEnd)
.Subtract((DateTime)p.DayStart).Days + 1));
I receive this error:
LINQ to Entities does not recognize the method
'System.TimeSpan Subtract(System.DateTime)' method, and this method cannot be
translated into a store expression.
How can I do this?
Use a calculated DB field and map that. Or use SqlFunctions with EF 4 as LukLed suggested (+1).
I wrote a function for removing time:
public static DateTime RemoveHours(DateTime date)
{
int year = date.Year;
int month = date.Month;
int day = date.Day;
return new DateTime(year, month, day);
}
and changed filtering condition:
var query =
from trn in context.IdentityTransactions
where trn.ClientUserId == userId && trn.DateDeleted == null
orderby trn.DateTimeCreated
select new
{
ClientServerTransactionID = trn.ClientServerTransactionID,
DateTimeCreated = trn.DateTimeCreated,
ServerTransDateTime = trn.ServerTransDateTime,
Timestamp = trn.Timestamp,
Remarc = trn.Remarc,
ReservedSum = trn.ReservedSum,
};
if (dateMin.HasValue && dateMin.Value > DateTime.MinValue)
{
DateTime startDate = Converters.RemoveHours(dateMin.Value);
query = from trn in query
where trn.DateTimeCreated >= startDate
select trn;
}
if (dateMax.HasValue && dateMax.Value > DateTime.MinValue)
{
var endDate = Converters.RemoveHours(dateMax.Value.AddDays(1.0));
query = from trn in query
where trn.DateTimeCreated < endDate
select trn;
}
dateMin and dateMax are nullable types and may be not set in my case.
Try (it is not very efficient, but it will work):
i.SpesaAlloggio = db.TDP_NotaSpeseSezB.ToList()
.Sum(p => p.Costo / (((DateTime)p.DayEnd)
.Subtract((DateTime)p.DayStart).Days + 1));
EDIT : This will be extremely slow for large tables, because it transfers whole table content form server
Entity Framework tries to translate your expression to SQL, but it can't handle ((DateTime)p.DayEnd).Subtract((DateTime)p.DayStart). You have to make it simpler. ToList() gets all rows and then makes the calculation on application side, not in database.
With EF4, you could use SqlFunctions DateDiff
With EF1, you could create calculated field or view with this field and make calculation based on this field.

Resources