sorting data based on month and date - asp.net-mvc-3

My db structure is following:
long OccasionId { get; set; }
string OccasionName { get; set; }
string OccasionDesc { get; set; }
DateTime OccasionDate { get; set; }
I need my result on html in following format
February
OccasionName1
5th February
OccasionDesc1
OccasionName2
7th February
OccasionDesc2
Now the data has to be sorted and grouped by month and then date but not year; means if there are two dates 05/02/1974 and 07/02/1970, even though the second date comes first because of the year, I need the sorting to be such that 5th feb comes first.
I'm using entity framework and asp.net mvc
Thanks
Arnab

Well, you don't mention your DB, but on SQL Server:
var q = from o in Context.Occasions
orderby o.Month, o.Day
select o;
...should work. Did you try that? However, it may or may not be efficient depending on the particulars of the rest of the query.

Related

Returning Most Recent Records Based on Serial Number

I have the following model
public class EngineComplianceMetric
{
public int Id { get; set; }
public DateTime BuildDate { get; set; }
public string SerialNumber { get; set; }
public bool Complied { get; set; }
}
SerialNumber isn't unique to the table, as the same item could have been repaired multiple times over the years.
I'm trying to return a list that only includes each Serial Numbers most recent record that's before some set date.
So far I have
previousCompliedList = _dbContext.ComplianceMetrics
.Where(e => e.BuildDate < startDate)
.Distinct().ToList();
But this is just returning everything prior to the startDate.
You have to group your items by serial numbers, then you have to take the most recent item in each group (by ordering them and taking the first).
previousCompliedList = _dbContext.ComplianceMetrics
.Where(cm => cm.BuildDate < startDate).ToList()
.GroupBy(cm => cm.SerialNumber)
.Select(cm => cm.OrderByDescending(c => c.BuildDate).First());
Based on your error, you have to add the .ToList() after the where (before the GroupBy). But doing this will fetch all the items from the DB where the date is smaller and then run additional manipulations on it in memory.
If you don't want to fetch all the items from the DB, you will have to implement a solution similar to Astrid's suggestion in the comments.
I would recommend googling your error messages: https://stackoverflow.com/a/60874316/7175057

how can i convert datetime exactly to sql server datetime using linq

I have two fields in Model class
public DateTime START_DATE { get; set; }
public DateTime END_DATE { get; set; }
and a Class
string format = "yyyy-MM-dd hh:mm:ss";
string startdate = timesheetModel.START_DATE.ToString(format, DateTimeFormatInfo.InvariantInfo);
string enddate = timesheetModel.END_DATE.ToString(format, DateTimeFormatInfo.InvariantInfo);
var weekid = from data in db.WEEK_CALENDER
where data.WEEK_START_DT ==Convert.ToDateTime(startdate) && data.WEEK_END_DT == Convert.ToDateTime(enddate)
select data.ID;
But Getting Error Convert.ToDateTimes is not possible in linq
and Also in Sql Server as format like
2014-03-03 00:00:00.000
I Have tried in different ways, but i think it needs exact same format of sql server format.
and Tried in that format also , but not getting.
pls help me anyone.
You don't need to convert your datetime to string, this can only cause trouble
public DateTime START_DATE { get; set; }
public DateTime END_DATE { get; set; }
var weekid = from data in db.WEEK_CALENDER
where data.WEEK_START_DT == START_DATE && data.WEEK_END_DT == END_DATE
select data.ID;
Unless you are managing different type of calendar, weeks don't overlap and they all contain 7 days, so you should only need to check the WEEK_START_DT (or only WEEK_END_DT) and you will only get 1 week, so you could do this instead :
var weekid = db.WEEK_CALENDER.Single(data => data.WEEK_START_DT == START_DATE).ID;
An other idea, your method receives a single date, and if returns the weekId which contains this date, it doesn't have to be the specific start of the week, it could be any date. This won't work of course if you are managing different type of weeks in your table.
var weekid = db.WEEK_CALENDER.Single(data =>
data.WEEK_START_DT <= A_DATE
&& data.WEEK_END_DT >= A_DATE
).ID;

Include nested entities using LINQ

I'm messing around with LINQ for the first time, and I'm using EF 4.1 code first.
I have entities containing nested Lists of other entities, for example:
class Release
{
int ReleaseID { get; set; }
string Title { get; set; }
ICollection<OriginalTrack> OriginalTracks { get; set; }
}
class OriginalTrack
{
int OriginalTrackID { get; set; }
string Title { get; set; }
ICollection<Release> Releases { get; set; }
ICollection<OriginalArtist> OriginalArtists { get; set; }
}
class OriginalArtist
{
int OriginalArtistID { get; set; }
string Name { get; set; }
ICollection<OriginalTrack> OriginalTracks { get; set; }
}
I'm wondering what is the quickest way, in one LINQ query, to obtain all the information for where ReleaseID == some value.
I've done my homework, but have found solutions that require implicit rebuilding of an object (usually anonymous) with the required data. I want the data out of the database in the exact format that it is held within the database, i.e. pulling a Release object with relevant ReleaseID pulls and populates all the OriginalTrack and OriginalArtist data in the Lists.
I know about Include(), but am not sure how to apply it for multiple entities.
All help greatly appreciated.
Use Include. This is the purpose of Include, and there's no reason to write a bunch of nested select statements.
context.Releases.Include("OriginalTracks.OriginalArtist")
.Where(release => release.ReleaseID == id);
This is simpler to write, simpler to read, and preserves your existing data structure.
To use Include you need to specify the name of the property you want to return - this means the name as it exists in your code, not in the database. For example:
.Include("OriginalTracks") will include the OriginalTracks property on each Release
.Include("OriginalTracks.OriginalArtist") will include OriginalTracks property on each Release, and the OriginalArtist on each Track (note that it's not possible - syntactically or logically - to include an OriginalArtist within including the OriginalTrack)
.Include("OriginalTracks").Include("OtherProperty") will include the OriginalTracks and OtherProperty objects on each Release.
You can chain as many of these as you like, for example:
.Include("Tracks.Artist").Include("AnotherProperty")
.Include("ThirdProperty.SomeItems").Where(r => r.something);
is perfectly valid. The only requirement is that you put the Include on the EntitySet, not on a query - you can't .Where().Include().
Don't worry about using include here
just do something like the following
var query =
from release in ctx.Releases
select new {
release,
originalTracks = from track in release.OriginalTracks
select new {
track,
releases = track.Releases,
orignialArtist = from artist in track.OriginalArtists
select new {
artist,
artist.OriginalTracks
}
}
}
var Releases = query.Select(x => x.Release);
Should load all of your data
I worked with information from this post here.
http://blogs.msdn.com/b/alexj/archive/2009/10/13/tip-37-how-to-do-a-conditional-include.aspx
To include the nested entities without using string literals, use Select, like this:
context.Releases.Include(r => r.OriginalTracks.Select(t => t.OriginalArtist))
.Where(release => release.ReleaseID == id);

Intellisense in linq projection after group by

I have a Collection<IStatements> statements which has
public interface IStatements
{
IDocuments Documents { get; set; }
string StatementDate { get; set; }
}
public class Documents : IDocuments
{
public string Date { get; set; }
public string Url { get; set; }
}
I would like to perform a group by on StatementDate and then do a projection.
When projecting if the group has more then one statement then I would like to club their statement date into 1. The problem is that I don't get Intellisense after groupby
var monthlyStatements = from mStatement in statements
orderby mStatement.StatementDate descending
group mStatement by mStatement.StatementDate;
I have tried following code
var monthlyStatements = from mStatement in statements
orderby mStatement.StatementDate descending
group mStatement by mStatement.StatementDate
into msStatement
select new
{
StatementDate =
mStatement.Documents.Date.,//no Intellisense
};
msStatement is going to be a grouping of IStatements, not a single IStatements. So you can do two things with it:
Get the Key property (which will be the statement date)
Get the contents of the group (which will each be an IStatements)
It's not really clear what you're trying to do with the multiple IStatements though.
The reason you haven't got dStatementDate any more is because you're using a query continuation; the only thing left is the grouping. Fortunately it's irrelevant here as you can get the statement date from the key; you can remove your "let" clause completely.

Linq expression for filtered collection of collections?

I'm hoping this will be a rather simple question for anyone who's good at Linq. I'm struggling to come up with the right Linq expression for the following. I'm able to hack something to get the results, but I'm sure there's a proper and simple Linq way to do it, I'm just not good enough at Linq yet...
I have a database accessed through Entity Framework. It has a number of Tasks. Each Task has a collection of TimeSegments. The TimeSegments have Date and Employee properties.
What I want is to be able to get the tasks for a certain employee and a certain month and the timesegments for each task for that same month and employee.
Again, the tasks do not in themselves have month nor date information, but they do by the TimeSegments associated with each task.
Very simplified it looks sort of like this:
public class Model //Simplified representation of the Entity Framework model
{
public List<Task> Tasks { get; set; }
}
public class Task
{
public int Id { get; set; }
public List<TimeSegment> TimeSegments { get; set; }
public Customer Customer { get; set; }
}
public class TimeSegment
{
public int Id { get; set; }
public string Date { get; set; }
public Employee Employee { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}
So how do I do this as simply as possible with Linq? I.e. tasks and associated timesegments for a certain month and employee. I would also like to be able to get it by Customer BTW...
This is the simplest thing I could come up with:
var tasksWithSegments =
from segment in model.TimeSegments
where segment.Date.Month == month
where segment.Employee.Id == employeeId
group segment by segment.Task into result
select new
{
Task = result.Key,
TimeSegments = result.ToArray()
};
Please note that you might have to add some properties to your model, such as Model.TimeSegment and TimeSegment.Task.
The trick with LINQ queries often is to start at the right collection. In this case the ideal starting point is TimeSegments.
ps. I'm not sure whether Date.Month == month will actually work with EF, but I think it will (with EF 4.0 that is).
Update:
Could you show how to extend this
query and get the tasks for a
particular Customer as well?
I'm not sure what you mean, but you can for instance filter the previous queryable like this:
var tasksWithSegmentsForCustomers =
from taskWithSegments in tasksWithSegments
where taskWithSegments.Task.Customer.Id == customerId
select taskWithSegments;
Can I get the return type to be a list
of Tasks with a list of TimeSegments
if I have this in a method?
Again, not sure what you exactly want, but if you want two separate lists that have no relation, you can do this:
List<Task> tasks = (
from taskWithSegments in tasksWithSegments
select taskWithSegments.Task).ToList();
List<TimeSegments> segments = (
from taskWithSegments in tasksWithSegments
from segment in taskWithSegments.Segments
select segment).ToList();
Of course, if this is what you need, than it might be easier to rewrite the original query to something like this:
List<TimeSegment> segments = (
from segment in model.TimeSegments
where segment.Date.Month == month
where segment.Employee.Id == employeeId
select segment).ToList();
List<Task> allTasks =
segments.Select(s => s.Task).Distinct().ToList();
Once you got the hang of writing LINQ queries, there is no way you want to go back to writing SQL statements or old-fashion foreach statements.
Think LINQ!!!
What I want is to be able to get the
tasks for a certain employee and a
certain month and the timesegments for
each task for that same month and
employee.
This will select tasks from an instance of Model where the task has at least one time segment that in the requested month for the requested employee (untested):
Model model = new Model();
tasks = model.Tasks.Where(t => t.TimeSegments.Any(ts => ts.Employee.Id = requestedId && Convert.ToDate(ts.Date).Month == requestedMonth));

Resources