I am trying to combine the date and time part of a table so that I can set appointments correctly I was wondering if someone could help me my syntax is not being compiled
public List<Appointment> getAppointments (DateTime AppointmentDate)
{
List<Appointment> query = _sourceEntities.Appointments.Where(a => a.ApptDate == AppointmentDate && a.ClientID==6).ToList();
return _sourceEntities.Appointments.Select(r =>
{
var newAppointment = new Appointment();
DateTime date = new DateTime(r.ApptDate.Year, r.ApptDate.Month, r.ApptDate.Day, r.ApptTime.Hour, r.ApptTime.Minute, r.ApptTime.Second);
newAppointment.ApptDate = date;
return newAppointment();
});
}
The error is hapening here return newAppointment(); I am not sure why its saying method name expected I want to have all the fields of the old list but also this new combined date time field.
Here is the example of the data to best explain
https://i.imgur.com/rCtx0lt.png
Edit 2
The _sourceEntites is decalred heree at the top of the class
public class SourceContext
{
public SMBASchedulerEntities _sourceEntities = new SMBASchedulerEntities();
public static List<Appointment> getAppointments(DateTime apptDate)
List<Appointment> query = _sourceEntities.Appointments.Where(a => a.ApptDate == AppointmentDate && a.ClientID==6).ToList();
return _sourceEntities.Appointments.Select(r =>
{
var newAppointment = new Appointment();
DateTime date = new DateTime(r.ApptDate.Year, r.ApptDate.Month, r.ApptDate.Day, r.ApptTime.Hour, r.ApptTime.Minute, r.ApptTime.Second);
newAppointment.ApptDate = date;
return newAppointment();
});
}
newAppointment is an object variable, by using ('s the compiler treats newAppointment as a method, that is what the error message states. Removing the ('s should solve the problem.
An alternative way to return the result would be
public List<Appointment> getAppointments (DateTime AppointmentDate)
{
List<Appointment> query = _sourceEntities.Appointments.Where(a => a.ApptDate == AppointmentDate && a.ClientID==6).ToList();
return _sourceEntities.Appointments.Select(r => new Appointment
{
newAppointment.ApptDate = ew DateTime(r.ApptDate.Year, r.ApptDate.Month, r.ApptDate.Day, r.ApptTime.Hour, r.ApptTime.Minute, r.ApptTime.Second);
//map other variables here
});
}
The problem with your code is in the line: return newAppointment();. You are treating the object newAppointment like a method when you add the parenthesis after it. Instead, you can just do:
return newAppointment;
A slightly simpler approach would be to create a new Appointment in your Select statement. This will return an IEnumerable of Appointment objects, which we can the call ToList() on before returning. I also included a .Where() clause to match what you had in your query. You can remove that line if it's not needed.
public static List<Appointment> getAppointments(DateTime apptDate)
{
return _sourceEntities.Appointments
.Where(a => a.ApptDate == apptDate && a.ClientID == 6) // Remove if not needed
.Select(r =>
new Appointment
{
ApptDate = new DateTime(r.ApptDate.Year, r.ApptDate.Month, r.ApptDate.Day,
r.ApptTime.Hour, r.ApptTime.Minute, r.ApptTime.Second)
})
.ToList();
}
One other thing to note is that you are doing an equality comparison on the two date objects, so you will only be getting appointments for the exact date and time of the argument passed in. In case you want to get all the appointments for the day, you can just use the Date portion of the DateTime objects for comparison:
// Compare the Date portion of the argument to get all appointments for that day
.Where(a => a.ApptDate.Date == appointment.Date && a.ClientID == 6)
Related
I need to generate a full month report base on some criteria. The first condition is- I am taking a anonyms Date from user and after checking all the condition it will generate full month report.
I tried to generate the report but this is returning a day wise report. Everything is fine except the month. Please help me to do this.
[HttpGet("inner-join/{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public IActionResult GetReport(DateTime id)
{
try
{
IEnumerable<BTBPending> objBTBPendingList = _unitOfWork.BTBPending.GetAll(includeProperties: "ProformaInvoice,ContractList,SupplierList,CountryList,ItemList,BuyerList,StyleList,TradeTermList,ErpRemarksList,StatusList,LcNoList,UdAmendList");
IEnumerable<ProformaInvoice> objProformaInvoiceList = _unitOfWork.ProformaInvoice.GetAll(includeProperties: "ActualContract,ContractList,SupplierList,CountryList,ItemList,BuyerList,StyleList,TradeTermList");
var query = objBTBPendingList
.Where(x => x.LcOpenDate == id)
.Where(x => x.CountryListId == 26)
.Where(x => x.StatusListId == 12 || x.StatusListId == 13 || x.StatusListId == 14)
.Join(objProformaInvoiceList,
btbPending => btbPending.ContractListId,
pi => pi.ContractListId,
(btbPending, pi) => new
{
LcNo = btbPending.LcNoList,
Value = btbPending.PiValue,
ContractNo = pi.ContractList,
Buyer = pi.BuyerList,
PiNo = pi.PINo,
Supplier = pi.SupplierList,
Item = pi.ItemList
}).ToList();
return Ok(query);
}
catch (Exception ex)
{
return StatusCode(500, "Internal Server Error, Please Try Again Leter!");
}
}
You have to make condition for the month, you are doing on the date. so do like this.
.Where(x => x.LcOpenDate.Month == id.Month && x.LcOpenDate.Year == id.Year)
Here I am assuming both id and LcOpenDate are from the same timezones.
As per the comment, LcOpenDate is DateTime?, so you need to do this.
LcOpenDate.Value.Month and LcOpenDate.Value.Year
DateTime gives your a full date and time and looks something like
2022-11-11 11:44:53 PM
What is likely going on is that when you are storing the data in the database, you are ommitting the time. Something like this:
var date = new DateTime(now.Year, now.Month, now.Day)
// 2022-11-11 12:00:00 AM
This is the only way x.LcOpenDate == id would work. Otherwise it would only return items with the open date at the exact time you provided up to the millisecond.
Try this instead:
.Where(x => x.LcOpenDate.Year == id.Year && x.LcOpenDate.Month == id.Month)
Additionally, if you are on .net 6+ you can use DateOnly and TimeOnly
I have an SQLite database of TimeRecords. When a new record is created, no EndTime is provided.
I want to retrieve the first record where the EndTime was not supplied and assign it to a new TimeRecord
EndTime is stored as a DateTime variable.
My Current Query
public static Models.TimeRecord GetMerchandiserCurrentTimeRecord(Models.Merchandiser merchandiser)
{
lock (collisionLock)
{
return database.Table<Models.TimeRecord>().FirstOrDefault(timeRecord => timeRecord.MerchandiserId == merchandiser.Id && timeRecord.EndTime == null);
}
}
Calling the Query
Models.TimeRecord CurrentTimeRecord { get; set; }
// I assign the CurrenTimeRecord in the Constructor
CurrentTimeRecord = Database.TimeRecordDatabase.GetMerchandiserCurrentTimeRecord(SelectedMerchandiser);
I have done some research and discovered that a DateTime does not store Null values, but instead defaults to the 1st January 0001 00:00:00.000.
Therefore, I can understand why my above query was not returning any result, so I changed the query to the below, but still I am not retrieving any result.
return database.Table<Models.TimeRecord>().FirstOrDefault(timeRecord => timeRecord.MerchandiserId == merchandiser.Id && timeRecord.EndTime == '01/01/0001');
I managed to solve this. Instead of checking against null or a string value I checked against a new instance of DateTime
Refer to below code
DateTime NoSuppliedDate = new DateTime();
return database.Table<Models.TimeRecord>().FirstOrDefault(timeRecord => timeRecord.MerchandiserId == merchandiser.Id && timeRecord.EndTime == NoSuppliedDate);
Edit: A better way was to use DateTime.MinValue as commented by #sqmoore.
class Bar
{
public DateTime Time { get; set; }
public double Price { get; set; }
}
class Instrument
{
public List<Bar> Bars { get; set; }
public string Name { get; set; }
public Instrument(string name, string path) {
// set the Bars list here reading from files
}
}
Here are two simplified versions of my classes. I'm creating a custom backtesting platform for currencies. The current problem is to chop off bars where I don't have price data on every instrument.
I read prices from an XML file.
var xlinqBarLists = xlinqInstruments.Select(i => i.Bars);
which is basically
List<List<Bar>> xlinqBarLists
What I want to do is loop through each individual list, find the latest start date and the earliest end date, then lop off all bars outside of that time window. My hacked together code is
var xlinqInstruments = root.Elements("instrument").Select( a =>
new Instrument( a.Element("name").Value, a.Element("path").Value ) );
var xlinqBarLists = xlinqInstruments.Select(i => i.Bars);
DateTime latestStartDate = DateTime.MinValue;
DateTime earliestEndDate = DateTime.MaxValue;
foreach (List<Bar> bars in xlinqBarLists)
{
if (bars.Min(b => b.Time) > latestStartDate)
latestStartDate = bars.Min(b => b.Time);
if (bars.Max(b => b.Time) < earliestEndDate)
earliestEndDate = bars.Max(b => b.Time);
}
foreach (List<Bar> barList in xlinqBarLists)
{
var timeWindowBars = from bar in barList
where bar.Time >= latestStartDate && bar.Time <= earliestEndDate
select bar;
// I need some way to overwrite the original Instrument.Bars property with timeWindowBars
// Suggestions?
}
Can I do this more quickly and efficiently by skipping the foreach loops?
For latest start date and earliest end date you can use
DateTime latestStartDate = xlinqInstruments.Max(i => i.Bars.Min(bar => bar.Time));
DateTime earliestEndDate = xlinqInstruments.Min(i => i.Bars.Max(bar => bar.Time));
And for the last part maybe you would like to add a parameterless constructor for ´Instrument´ and then
var result = xlinqInstruments
.Select(i=>new Instrument()
{
Name = i.Name,
Bars = i.Bars.Where(bar => bar.Time >= latestStartDate
&& bar.Time <=earliestEndDate)
.ToList()
});
Here's an answer if my comment above, (which I've copy/pasted below) turns out to be the case.
Are you wanting to set the Bars property of each instrument to a
List containing only those objects that fall within the minimum
end date and maximum start date across all Bar objects (including
those present on other Instruments)?
// Get the value of the earliest Bar.Time on each Instrument, and select the most recent of those.
DateTime latestStartDate = xlinqInstruments.Max(instrument => instrument.Bars.Min(bar => bar.Time));
// Get the value of the latest Bar.Time on each Instrument, and select the earliest of those.
DateTime earliestEndDate = xlinqInstruments.Min(instrument => instrument.Bars.Max(bar => bar.Time));
// Overwrite the Bars collection of each instrument with its contents truncated appropriately.
// I'd suggest doing this with a foreach loop as opposed to what I've provided below, but that's just me.
xlinqInstruments.ForEach(instrument =>
{
instrument.Bars = instrument.Bars.Where(obj => obj.Time >= latestStartDate && obj.Time <= earliestEndDate).ToList();
});
It may be worth nothing that the ForEach method requires you to call .ToList() on the xlinqInstruments collection first. In my code, I assume the collection has already been materialized to List<Instrument>
You may also be interested in linq's Enumerable.SelectMany method.
Enumerable.SelectMany Method (IEnumerable, Func>)
Projects each element of a sequence to an IEnumerable and flattens the resulting sequences into one sequence.
Call ToList before assigning to xlinqBarLists:
var xlinqBarLists = xlinqInstruments.Select(i => i.Bars).ToList();
Otherwise you're parsing the same XML over and over again.
You should most likely call ToList when creating xlinqInstruments as well, if you want to update them later.
I am having two date values, one already stored in the database and the other selected by the user using DatePicker. The use case is to search for a particular date from the database.
The value previously entered in the database always has time component of 12:00:00, where as the date entered from picker has different time component.
I am interested in only the date components and would like to ignore the time component.
What are the ways to do this comparison in C#?
Also, how to do this in LINQ?
UPDATE:
On LINQ to Entities, the following works fine.
e => DateTime.Compare(e.FirstDate.Value, SecondDate) >= 0
Use the class EntityFunctions for trimming the time portion.
using System.Data.Objects;
var bla = (from log in context.Contacts
where EntityFunctions.TruncateTime(log.ModifiedDate) == EntityFunctions.TruncateTime(today.Date)
select log).FirstOrDefault();
Source: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/84d4e18b-7545-419b-9826-53ff1a0e2a62/
UPDATE
As of EF 6.0 and later EntityFunctions is replaced by DbFunctions.
NOTE: at the time of writing this answer, the EF-relation was unclear (that was edited into the question after this was written). For correct approach with EF, check Mandeeps answer.
You can use the DateTime.Date property to perform a date-only comparison.
DateTime a = GetFirstDate();
DateTime b = GetSecondDate();
if (a.Date.Equals(b.Date))
{
// the dates are equal
}
I think this could help you.
I made an extension since I have to compare dates in repositories filled with EF data and so .Date was not an option since it is not implemented in LinqToEntities translation.
Here is the code:
/// <summary>
/// Check if two dates are same
/// </summary>
/// <typeparam name="TElement">Type</typeparam>
/// <param name="valueSelector">date field</param>
/// <param name="value">date compared</param>
/// <returns>bool</returns>
public Expression<Func<TElement, bool>> IsSameDate<TElement>(Expression<Func<TElement, DateTime>> valueSelector, DateTime value)
{
ParameterExpression p = valueSelector.Parameters.Single();
var antes = Expression.GreaterThanOrEqual(valueSelector.Body, Expression.Constant(value.Date, typeof(DateTime)));
var despues = Expression.LessThan(valueSelector.Body, Expression.Constant(value.AddDays(1).Date, typeof(DateTime)));
Expression body = Expression.And(antes, despues);
return Expression.Lambda<Func<TElement, bool>>(body, p);
}
then you can use it in this way.
var today = DateTime.Now;
var todayPosts = from t in turnos.Where(IsSameDate<Turno>(t => t.MyDate, today))
select t);
If you use the Date property for DB Entities you will get exception:
"The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."
You can use something like this:
DateTime date = DateTime.Now.Date;
var result = from client in context.clients
where client.BirthDate >= date
&& client.BirthDate < date.AddDays(1)
select client;
To do it in LINQ to Entities, you have to use supported methods:
var year = someDate.Year;
var month = ...
var q = from r in Context.Records
where Microsoft.VisualBasic.DateAndTime.Year(r.SomeDate) == year
&& // month and day
Ugly, but it works, and it's done on the DB server.
Here's a different way to do it, but it's only useful if SecondDate is a variable you're passing in:
DateTime startDate = SecondDate.Date;
DateTime endDate = startDate.AddDays(1).AddTicks(-1);
...
e => e.FirstDate.Value >= startDate && e.FirstDate.Value <= endDate
I think that should work
You can also use this:
DbFunctions.DiffDays(date1, date2) == 0
you can use DbFunctions.TruncateTime() method for this.
e => DbFunctions.TruncateTime(e.FirstDate.Value) == DbFunctions.TruncateTime(SecondDate);
Just always compare the Date property of DateTime, instead of the full date time.
When you make your LINQ query, use date.Date in the query, ie:
var results = from c in collection
where c.Date == myDateTime.Date
select c;
This is how I do this.
DateTime date_time_to_compare = DateTime.Now;
//Compare only date parts
context.YourObject.FirstOrDefault(r =>
EntityFunctions.TruncateTime(r.date) == EntityFunctions.TruncateTime(date_to_compare));
//Note for Linq Users/Coders
This should give you the exact comparison for checking if a date falls within range when working with input from a user - date picker for example:
((DateTime)ri.RequestX.DateSatisfied).Date >= startdate.Date &&
((DateTime)ri.RequestX.DateSatisfied).Date <= enddate.Date
where startdate and enddate are values from a date picker.
Without time than try like this:
TimeSpan ts = new TimeSpan(23, 59, 59);
toDate = toDate.Add(ts);
List<AuditLog> resultLogs =
_dbContext.AuditLogs
.Where(al => al.Log_Date >= fromDate && al.Log_Date <= toDate)
.ToList();
return resultLogs;
You can user below link to compare 2 dates without time :
private bool DateGreaterOrEqual(DateTime dt1, DateTime dt2)
{
return DateTime.Compare(dt1.Date, dt2.Date) >= 0;
}
private bool DateLessOrEqual(DateTime dt1, DateTime dt2)
{
return DateTime.Compare(dt1.Date, dt2.Date) <= 0;
}
the Compare function return 3 different values: -1 0 1 which means dt1>dt2, dt1=dt2, dt1
Try this... It works fine to compare Date properties between two DateTimes type:
PS. It is a stopgap solution and a really bad practice, should never be used when you know that the database can bring thousands of records...
query = query.ToList()
.Where(x => x.FirstDate.Date == SecondDate.Date)
.AsQueryable();
I have resolved error using EfCore FromSqlRaw method.
var sql =
$"select * from \"ProgressBooks\" where date(\"Date\") = date('{today.Date.ToString("yyyy-MM-dd")}') and \"GroupId\" = {groupId}";
var todayProgressBook = _context.ProgressBooks.FromSqlRaw(sql).FirstOrDefault();
I have an array of classes with a property Date, i.e.:
class Record
{
public DateTime Date { get; private set; }
}
void Summarize(Record[] arr)
{
foreach (var r in arr)
{
// do stuff
}
}
I have to find the earliest (minimum) and the latest (maximum) dates in this array.
How can I do that using LINQ?
If you want to find the earliest or latest Date:
DateTime earliest = arr.Min(record => record.Date);
DateTime latest = arr.Max(record => record.Date);
Enumerable.Min, Enumerable.Max
If you want to find the record with the earliest or latest Date:
Record earliest = arr.MinBy(record => record.Date);
Record latest = arr.MaxBy(record => record.Date);
See: How to use LINQ to select object with minimum or maximum property value
old school solution without LINQ:
DateTime minDate = DateTime.MaxValue;
DateTime maxDate = DateTime.MinValue;
foreach (var r in arr)
{
if (minDate > r.Date)
{
minDate = r.Date;
}
if (maxDate < r.Date)
{
maxDate = r.Date;
}
}
The two in one LINQ query (and one traversal):
arr.Aggregate(
new { MinDate = DateTime.MaxValue,
MaxDate = DateTime.MinValue },
(accDates, record) =>
new { MinDate = record.Date < accDates.MinDate
? record.Date
: accDates.MinDate,
MaxDate = accDates.MaxDate < record.Date
? record.Date
: accDates.MaxDate });
Using lambda expressions:
void Summarise(Record[] arr)
{
if (!(arr == null || arr.Length == 0))
{
List<Record> recordList = new List<Record>(arr);
recordList.Sort((x,y) => { return x.Date.CompareTo(y.Date); });
// I may have this the wrong way round, but you get the idea.
DateTime earliest = recordList[0];
DateTime latest = recordList[recordList.Count];
}
}
Essentially:
Sort into a new list in order of date
Select the first and last elements of that list
UPDATE: Thinking about it, I'm not sure that this is the way to do it if you care at all about performance, as sorting the entire list will result in many more comparisons than just scanning for the highest / lowest values.
I'd just make two properties Min,Max, assign them the value of the first item you add to the array, then each time you add a new item just check if its DateTime is less or greater than the Min Max ones.
Its nice and fast and it will be much faster than iterating through the array each time you need to get Min Max.