Presenting data from database without multiplying specific field - c#

I have something like this in database:
and I want to display it like this:
date1 worktime UserName1
date2 worktime
date3 worktime
date1 worktime UserName2
date2 worktime
date3 worktime
I've cereated a Model:
[Table("Work_Hours")]
public class User
{
public string UserID { get; set; }
public string UserName { get; set; }
public TimeSpan WorkTime { get; set; }
public DateTime Date { get; set; }
}
public class UserDBContext : DbContext
{
public DbSet<User> Users { get; set; }
}
And tried to solve my problem with ViewModel:
public class UserViewModel
{
public string UserID { get; set; }
public string UserName { get; set; }
public LinkedList<TimeSpan> WorkTime { get ; set;}
public LinkedList<DateTime> Date { get; set; }
}
But I don't know how add only one object and list of WorkTime and Date to new list of viewmodels for one specific UserName from list of models.

Linq already has this built in. Given:
IEnumerable<User> data=...; // input from somewhere
You can do:
var groups=data.GroupBy(w=>w.UserName); // type is IGrouping<string, User>
Enumerating this object will give you a Key property which is the username, once for each item, then enumerating this returning object again will give you every item that has the specified username.

Related

Using part of the Date in a ViewSource Grouping Description WPF C#

I have a ViewSource based on an observable collection of a set of objects based on a c# class called "Ticket" for a DataGrid for a WPF project in C# .net 4. The project is for a simple Helpdesk app.
The ViewSource Grouped on a Property call TktDate and all the tickets entered that day obviously grouped together in my DataGrid
However I have recently updated the code so the TktDate now not only stores the Date element but also the Time element, so clearly when I mean to Group on the Date only I am failing to do this because of the time elements (Am I correct?).. So if that was not clear here is a screen shot
Is there a way to Group on the date part TktDate and ignore the time element for my ViewSource or must I add a new property to my class to store the date part only and group on the new property?
See the properties of the class below
public class Ticket : INotifyPropertyChanged
{
public int userid { get; set; }
public int deptid { get; set; }
public int topicid { get; set; }
public int staffid { get; set; }
public int priorityid { get; set; }
public string poster { get; set; }
public DateTime TktDate { get; set; }
public string title { get; set; }
public string bodyopen { get; set; }
public string bodyclose { get; set; }
public string timespent { get; set; }
public string dayoffset { get; set; }
public string sysdt { get; set; }
public string Netdt { get; set; }
public string Teldt { get; set; }
public string Clidt { get; set; }
public string status { get; set; }
private string ticket;
public string Tket
In the ViewSource I group on the TktDate, which records the date the ticket is created. The grouping code is below and it worked fine
CollectionViewSource ticketViewSource = ((CollectionViewSource)(this.FindResource("ticketViewSource")));
ticketViewSource.Source = TicketCol;
ticketDataGrid.DataContext = ticketViewSource;
//add grouping
if (ticketViewSource != null)
{
ticketViewSource.GroupDescriptions.Clear();
ticketViewSource.GroupDescriptions.Add(new PropertyGroupDescription("TktDate"));
ticketViewSource.SortDescriptions.Clear();
ticketViewSource.SortDescriptions.Add(new SortDescription("TktDate", ListSortDirection.Ascending));
}
Is there a way to Group on the date part TktDate and ignore the time element for my ViewSource or must I add a new property to my class to store the date part only and group on the new property?
You may try to group by a nested property:
ticketViewSource.GroupDescriptions.Add(new PropertyGroupDescription("TktDate.Date"));
If this doesn't work you should add a new DateTime read-only property to your Ticket class that returns TktDate.Date and group by this one.

DbContext Set with where query using database first approach EF

I have a database first project with ADO.NET Entity Data model generated classes. All of my classes have same boolean and datetime fields, Ok and Date. I want to create generic method for retrieving T class from DbContext but i'm not sure how to use where in that query since i cant access Ok and Date fields.
note: i can't change generated classes, and i would want to avoid using Linq.Dynamic
ADO.Net generated
public partial class First
{
public int Id { get; set; }
public string NameFirst { get; set; }
public DateTime Date { get; set; }
public bool Ok { get; set; }
}
public partial class Second
{
public int Id { get; set; }
public string NameSecond { get; set; }
public DateTime Date { get; set; }
public bool Ok { get; set; }
}
Retrieve data
public List<SomeModel> LoadFromDatabase<T>(bool ok, DateTime date)
{
var dbData = DbContext.Set(typeof(T)).AsNoTracking().Where(x => x.Ok ??? );
//remap to some model and return it
...
return someModel;
}
Edit 1:
public List<SomeModel> LoadFromDatabase<T>(bool ok, DateTime date) where T : IDateOk
{
var dbData = DbContext.Set(typeof(T)).AsNoTracking().Where(x => x.Ok &&);
//remap to some model and return it
...
return someModel;
}
public interface IDateOk {
DateTime Date { get; set; }
bool Ok { get; set; }
}
Edit 2:
I was missing class in method so it should be like this
public List<SomeModel> LoadFromDatabase<T>(bool ok, DateTime date) where T : class IDateOk
Define an interface for the common properties:
public interface IDateOk {
DateTime Date { get; set; }
bool Ok { get; set; }
}
Here is a tutorial how to add the interface to the generated classes:
Getting the Entity Framework to Generate an Interface for Mocking
Constrain your method to require this interface:
public List<SomeModel> LoadFromDatabase<T>(bool ok, DateTime date) where T: IDateOk
Now you should be able to access OK and Date in the implementation.

MVC datetime list not saving

I have a simple MVC4 model that adds a DateTime.Now to a List<DateTime>() list.
However when I do an EntityState.Modified, the changes are not being kept.
I've debugged this by modifying another property in the model and that saves fine.
So I really am at a loss as to why this is not saving. If anyone has any ideas as to why its not saving that would be life saver material:
The Model:
public class Page
{
public int Id { get; set; }
public string PageURL { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public List<DateTime> Visits { get; set; }
public Page()
{
Visits = new List<DateTime>();
}
}
Here's my code:
private ApplicationDbContext db = new ApplicationDbContext();
public ActionResult CookiePolicy()
{
var page = db.Pages.FirstOrDefault(c => c.PageURL == "cookiepolicy");
page.Visits.Add(DateTime.Now); // this list of datetime objects does not get updated
page.Title = "test "; //but this property does
ViewBag.Title = page.Title;
db.Entry(page).State = EntityState.Modified;
db.SaveChanges();
return View(page);
}
Edit Fabio Luz mentioned:
"collection of primitive types (like int, DateTime, bool) are not
supported"
So the solution below seems like the right option.
Ok, so after some deliberation. I decided to create a new model called vist and have this as the list instead of datetime:
public class Visit
{
public int Id { get; set; }
public DateTime DateTime { get; set; }
public BrowserType BrowserType { get; set; }
public String Duration { get; set; }
public int PageId { get; set; }
public virtual Page Page { get; set; }
public Visit()
{
DateTime = DateTime.Now;
BrowserType = BrowserType.Other;
}
}
There are benefits to this. Now I can store more information then just the datetime.
So for anyone who had the same problem as me. Consider pushing it out into its own model for greater flexibility.
Like Fabio Luz mentioned in his comment primitive type collections aren't supported. A collection within an class retrieved from a context is generally assumed to represent a One-to-Many / Many-to-Many relationship.
When building models keep in mind how they would be represented in a SQL table, and having a column that has a collection within is not supported in such a structure. Now, if you were referencing another object (table) than the object (table record) would have certain properties, such as a primary key etc.
Hope this helps.
Edit:
Here is a sample model you might want to consider:
public class Page
{
public int Id { get; set; }
public string PageURL { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public virtual IQueriable<Visit> Visits { get; set; }
}
public class Visit
{
// ... properties related to data you wish to retain about the visit
public virtual Page Page { get; set; } // navigation property
}

models for input and models for views, do you separate? c#

I have Some model, for example: RequestModel
public class RequestModel
{
public int RequestId { get; set; }
public int CategoryKey { get; set; }
public int SubCategoryKey { get; set; }
public int AreaKey { get; set; }
}
This model I use to get input from some html form.
CategoryKey, SubCategoryKey, and AreaKey, are codes for the Category, Subcategory and the Area values.
For display purposes I need to show the CategoryValue, SubCategoryValue and AreaValue. So I use the same model for my View and added the three fields to it.
public class RequestModel
{
public int RequestId { get; set; }
public int CategoryKey { get; set; }
public int SubCategoryKey { get; set; }
public int AreaKey { get; set; }
public String CategoryValue { get; set; }
public String SubCategoryValue { get; set; }
public String AreaValue { get; set; }
}
I'm thinking of separate it to the following classes:
public class RequestModel
{
public int RequestId { get; set; }
}
public class RequestInputModel : RequestModel
{
public int CategoryKey { get; set; }
public int SubCategoryKey { get; set; }
public int AreaKey { get; set; }
}
public class RequestDisplayModel : RequestModel
{
public int RequestId { get; set; }
public String CategoryValue { get; set; }
public String SubCategoryValue { get; set; }
public String AreaValue { get; set; }
}
What do you think? is it really necessary? do you do this separation between classes for input and classes for display?
The General Best Practice is that you have your Data in the model. ie information that you need to save to a file or database, you then have your business logic on a View Model, this would be things like the Fullname being a First + Surname and the like, so data that needs to be displayed but not saved
then you have your View on top that formats and styles your output
so you would have
public class PersonModel
{
string firstName;
string Surname;
DateTime DateOfBirth
}
public class PersonDisplayViewModel
{
PersonModel Model;
string FullName
{
get{return Model.firstname + " " + Model.Surname;}
}
int Age
{
get{return (DateTime.Today() - Model.DateOfBirth).TotalYears;}
}
}
public class PersonEditViewModel
{
PersonModel Model;
string FirstName {
get{return Model.FirstName;}
set{Model.FirstName = value;}
}
string Surname{
get{return Model.Surname;}
set{Model.Surname= value;}
}
DateTime DateOfBirth{
get{return Model.DateOfBirth;}
set{Model.Surname= DateOfBirth;}
}
}
The reason for this is that the same core data may be used in many places, say you have a search screen that shows Full name and age and an editing screen that lets you edit first and last name and date of birth. they have the same core data of person but they present the data in different ways. also say you were doing something for a School and wanted to make sure a students age is <16 but you also have staff that have to be >18. you can't put this age filter on the person Model as a person can be any age, but would fit perfectly well on the view model that is defining what can and can't be written to the under lying model
the same is true for views if you have a version of your app in USA you want to use American Date Format ie mm-dd-yyyy but the same app in UK would need the dd-mm-yyyy format does this have any effect on the underlying data or business logic? No it just changes the appearance of the data so goes in the veiw

Storing actual repeating date's without the year part

Using the Entity Framework data access model, I am attempting to store Clubs including their meeting day/time information. Instead of using a free text field for the user to write something on the lines of "We meet on a Wednesday 5-6 and Thursday 7-8" I instead wish to store the meeting day and times in a more meaningful format.
I have a Club model something along the lines of:
public class Club
{
public bool VisuallyImpairedWelcome { get; set; }
public string Explanation { get; set; }
public List<CalendarEntry> MeetingDays { get; set; }
public DateTime DateCreated { get; set; }
}
CalendarEntry model looks like:
public class CalendarEntry
{
public int CalendarEntryId { get; set; }
public int ClubId { get; set; }
public Days Day { get; set; }
public DateTime From { get; set; }
public DateTime To { get; set; }
public Intervals Interval { get; set; }
public List<ExceptionDays> ExceptionDays { get; set; }
public string AdditionalInfo { get; set; }
}
The problem im having is with the List<ExceptionDays>, my thinking here would be the user could set up their regular meeting days i.e:
Monday 17:00 - 18:30
Wednesday 17:30 - 18:30
Occurrence: Every Week
Except Yearly: 25th December 26th December
Something along these lines, the problem is I have no idea how I should construct my ExceptionDays class, something along the lines of (pseudo:)
public class ExceptionDays
{
int Day { get; set; }
int Month { get; set; }
}
But obviously the Day/Month combination must be possible, and the date is to be excluded as this will be a re-occurring date.
Firstly am I taking the right approach here, if so how can I construct a water tight ExceptionDays class?

Categories