Perform a calculation in MVC viewmodel - asp.net-mvc

Trying to perform a calculation in a view model. I have two donation columns, want to add them together in the viewmodel.
This is in the ViewModel Class:
[DataType(DataType.Currency)]
public decimal ttlDonation
{
get { return Donation.GetValueOrDefault() + GuestDonation.GetValueOrDefault(); }
}
The Viewmodel builds fine, and it displays properly in the razor view using (modelItem => item.ttlDonation). Problem is when I try to SUM this expression with a LINQ query in the controller like so:
var DonateTTl = GuestViewModel.Sum(f => f.ttlDonation);
Then my code throws an error:
The specified type member 'ttlDonation' is not supported in LINQ to Entities...
I am wondering the best way to do this. I also tried this in my controller (below), where I've changed my viewmodel slightly to a basic get; set; and it still isn't working. What is the best way to do this? Should I perform the calculation on my original Model rather than my viewmodel?
var GuestViewModel = guests.Select(g => new GuestIndexViewData
{
ID = g.ID,
FRID = g.FRID,
FirstName = g.FirstName,
LastName = g.LastName,
Company = g.Company,
email = g.email,
Donation = g.Donation,
GuestFirstName = g.GuestFirstName,
GuestLastName = g.GuestLastName,
GuestCompany = g.GuestCompany,
Guestemail = g.Guestemail,
GuestDonation = g.Donation,
Attended = g.Attended,
RSVP = g.RSVP,
Guest3 = g.Guest3,
ttlDonation = (g.GuestDonation.GetValueOrDefault() + g.Donation.GetValueOrDefault())
}).OrderBy(f => f.FRID);
var DonateTTl = GuestViewModel.Sum(f => f.ttlDonation);
I know I can find a way to do this but I am looking for the best way to do this as for standards/performance.

I think picking it out will work:
var DonateTTl = GuestViewModel.Select(vm => vm.ttlDonation).Sum();

Related

Entity Framework eager loading navigation property causes error when using user-defined type

Some background
I'm wanting to bind a list of objects (my model-view) to a grid. The model-view contains fields for both an specific entity and fields from a joined entity.
I was getting an error when I would try to bind due to the dbContext being out of scope. I realized I needed to use the .Include() method in order to eager load my navigation property. However, I suspect that since I'm using Linq to Entities, that I'm now generating another error:
"Unable to cast the type 'System.Linq.IQueryable1' to type 'System.Data.Objects.ObjectQuery1'. LINQ to Entities only supports casting EDM primitive or enumeration types."
My code is shown below, any ideas of what I need to do here?
Thanks in advance!
public static List<PlanViewModel> GetPlans()
{
using (var context = new RepEntities())
{
var query = (from p in context.Plans
join r in context.RealEstateDetails on p.ReId equals r.ReId
select new PlanViewModel
{
PlanName = p.PlanName,
TargetCompletionDate = p.TargetCompletionDate,
ActualCompletionDate = p.ActualCompletionDate,
Provision = p.Provision,
StatusTypeId = p.StatusTypeId,
StatusCommon = p.StatusCommon,
Building = r.BuildingName,
City = r.City,
Country = r.Country
}).Include("StatusCommon");
return query.ToList();
}
}
You are almost there, just put Include("StatusCommon") right after context.Plans. Because you need to include StatusCommon before the iteration, this way you can set StatusCommon value for every iteration.
public static List<PlanViewModel> GetPlans()
{
using (var context = new RepEntities())
{
var query = (from p in context.Plans.Include("StatusCommon")
join r in context.RealEstateDetails on p.ReId equals r.ReId
select new PlanViewModel
{
PlanName = p.PlanName,
TargetCompletionDate = p.TargetCompletionDate,
ActualCompletionDate = p.ActualCompletionDate,
Provision = p.Provision,
StatusTypeId = p.StatusTypeId,
StatusCommon = p.StatusCommon,
Building = r.BuildingName,
City = r.City,
Country = r.Country
}).toList();
return query;
}
}

MVC partial views, and complex Models

I'm trying to populating a nested Model
The model looks something like this
public Layout {
public List<Record> Records {get;set;}
}
public Record {
public List<PlaceHolder> PlaceHolders {get;set;}
}
public PlaceHolder {
public string Label {get;set;}
}
When my form posts, using fiddler, I see that the values coming down with keys in the format
Records.Index = 0
Records.PlaceHolders.Index = 0
Records[0].PlaceHolders[0].Label = foo
Records.Index = 0
Records.PlaceHolders.Index = 1
Records[0].PlaceHolders[1].Label = bar
Records.Index = 1
Records.PlaceHolders.Index = 1
Records[1].PlaceHolders[1].Label = boo
...
A lot of these KeyNames I had to generate myself using partial views, padding a TemplateInfo with the HtmlFieldPrefix set.
When I look at my save controller, the Layout is only partially populated. It has all it's Records in the Records property. But none of the Records contain PlaceHolders.
What is wrong with my post keys?
Got it, I need these lines
Records.PlaceHolders.Index = 0
To have the Record's Index, like so
Records[1].PlaceHolders.Index = 0

Count books of user with Linq-To-Sql

I'm new in linq and i have a simple problem.
i must count how many books have user.
i know its easy but i cant do this.
//database
public List<UserViewModel> GetAllUsers()
{
var result = from u in databaseContext.User
select new UserViewModel
{
UserId = u.UserId,
LastName = u.LastName,
FirstName = u.FirstName,
BirthDate = u.BirthDate,
Email = u.Email,
Phone = u.Phone,
AddDate = u.AddDate,
ModifiedDate = u.ModifiedDate,
IsActive = u.IsActive,
};
return result.ToList();
}
how to do this?
In your model it seems that every Borrow has exactly one Book associated with it. If that is the case and the books cannot be taken more than once (which should be also correct) then all you need to do is:
int count = context.Users.First(x=>x.UserId = 1).Borrow.Count();
This way you can count all the Borrows of a given user supposing that they are all associated with a book.
If two borrows can have the same book than you should slightly rewrite this query to this:
int count = db.Borrow.Where(x => x.UserID== 1).Select(x => x.BookId).Distinct().Count();
This way you will get only the unique books borrowed from the user with id of 1.
To count only the unique books that are not returned use this:
int count = db.Borrow.Where(x => x.UserID== 1 && x.IsReturned == false).Select(x => x.BookId).Distinct().Count();

Entity Framework - Unable to create a constant value of type x. Only primitive types are supported in this context.

I have the following
A Engineer Model:
public class engineers
{
public Guid? Guid { get; set; }
public string Name { get; set; }
}
I fill the a list of engineers with the correct details:
List<engineers> listeng = new List<engineers>();
listeng.Add(new engineers { Name = profile.FirstName + " " + profile.LastName, Guid = GuidEngineer });
So far so good.
My question how can I pull the engineers name to the eng entry below:
var tickets = from o in new HelpdeskEntities().Tickets.Where(t => t.TicketState.State == "Open")
select new AjaxTickets
{
TicketID = o.TicketID,
TicketSubject = o.TicketSubject,
ClientCompanyName = o.ClientCompany.ClientCompanyName,
DateOpened = o.DateOpened,
**eng** = list.Where(x => x.Guid == o.EngineerID).Select(x => new engineers {Guid = x.Guid, Name=x.Name }).FirstOrDefault().Name
};
I've also tried
var tickets = from o in new HelpdeskEntities().Tickets.Where(t => t.TicketState.State == "Open")
select new AjaxTickets
{
TicketID = o.TicketID,
TicketSubject = o.TicketSubject,
ClientCompanyName = o.ClientCompany.ClientCompanyName,
DateOpened = o.DateOpened,
**eng** = list.Where(x => x.Guid == o.EngineerID).Select(x => x.Name }).FirstOrDefault()
};
The error i'm getting is:
Unable to create a constant value of type 'Helpdesk2.ViewModel.engineers'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."}
Which I kinda of understand but cannot figure out away just to select the engineer name.
Thanks in advance
You should be able to simplify the first one to:
list.FirstOrDefault(x => x.Guid == o.EngineerID).Name
Having said that, Entity Framework probably won't let you run that when running a database call. If you can make a foreign key from ticket to engineer, then you can select it in the same way as you do the client company name. If not, then you'll need to do it in two goes: first, run the select without populating the engineer name property, and after that, fill them in with something like:
tickets.ForEach(ticket => ticket.EngineerName = engineers.First(eng => eng.Guid == ticket.EngineerID).Name)
Obviously you'll need to add the EngineerID property and select it in the first step.

Binding pivot query to view in ASP.Net MVC

I'm sticking on how to best present some data that's being dynamically generated from two different tables.
Given my query:
var assets = assetRepo.Find(x => x.LoginId == User.Identity.Name);
var accounts = repository.Find(x => x.AccStatus == "A" && x.LoginId == User.Identity.Name);
var query = from asst in assets
join acct in accounts on asst.AccountId equals acct.AccountId
select new
{
Account = acct.AccountNumber,
Status = acct.AccStatus,
Make = asst.Make,
Model = asst.Model,
Submodel = asst.SubModel,
Registration = asst.Registration,
Balance = acct.BalanceOutstanding,
NextPayment = acct.NextPayment,
Date = String.Format("{0:dd MMM yyyy}", acct.NextPaymentDate),
Due = acct.ArrearsBal
};
What would be the best (i.e. cleanest) way to bind this to the view? Would a custom class be required or is there a way to specify and iterate over a collection of anonymous types?
Creating custom class can give you additional benefits. You can use DisplayAttribute to set column headers and order. Then you can create view (or template to use with DisplayFor) that takes list of objects of any type and uses reflection to read annotations and display view nicely.
class Report {
[Display(Name="Account",Order=1)]
public string Account {get; set;}
[Display(Name="Next payment",Order=2)]
public Date NextPayment {get; set;}
}
It looks also clean. You will be able to use this annotations not only for grid, but also for excel exports or other data operations.

Resources