Reputation: 4067
My dbstructure is as follows
StudentRegistrationTable
Id Name
5 Sachin
StudentReceiptTable
Id StudRegId Fee ST Total Status DueDate
1 5 873 127 1000 1 01/05/2016
2 5 873 127 2000 1 01/15/2016
3 5 873 127 3000 0 01/25/2016
4 5 873 127 4000 0 01/28/2016
5 5 873 127 5000 0 01/30/2016
Status indicates the payment mode.Status 1 indicates student has paid the receipt and 0 indicates the unpaid receipt
Query
_dTableReg = _db.StudentRegistrations
.AsEnumerable()
.Where(r => (..condition))
.Select(r => new RegistraionVM.RegDataTable
{
...
...
NextDueAmount = r.StudentReceipts.
Where(rc => rc.Status == false)
.First().Total.ToString(),
NextDueDate = r.StudentReceipts.
Where(rc => rc.Status == false)
.First().DueDate.Date.ToString('dd/MM/yyyy')
}).OrderByDescending(r => r.RegistrationID).ToList();
The above query returns the first unpaid amount and date(3000 & 01/25/2016).
The problem arises when student has paid all the receipt (ie status will be set to 1) and i am getting Sequence contains no elements errror
.In that case I want to return FULL PAID
in both NextDueAmount
and NexDueDate
RegDataTable Class
public class RegDataTable
{
...
...
public string NextDueAmount { get; set; }
public string NextDueDate { get; set; }
}
Upvotes: 0
Views: 1497
Reputation:
Your use of .First()
will throw the error is the collection of StudentReceipt
returns no items (i.e. when the Status
of all items is true
). You need to use .FirstOrDefault()
and then check if the value is null
, and if not then access the Total
and DueDate
properties.
This could make you controller code unnecessarily complex (and your also accessing the database twice to get the collection) so I suggest you use a view model (if its not already) with additional read only properties to return the results
public class RegDataTableVM
{
....
public StudentReceipt Receipt { get; set; }
public string NextDueAmount
{
get { return Receipt == null ? "FULL PAID" ? Receipt.Total.ToString() }
}
public string NextDueDate
{
get { return Receipt == null ? "FULL PAID" ? Receipt.DueDate.ToString("dd/MM/yyyy") }
}
and modify the query to
_dTableReg = _db.StudentRegistrations
.Where(r => (..condition))
.Select(r => new RegDataTableVM
{
...
...
Receipt = r.StudentReceipts.Where(rc => rc.Status == false).FirstOrDefault()
}).OrderByDescending(r => r.RegistrationID).ToList();
Side note: If your using DisplayFor()
to generate the html, you can also make use of the DisplayFormatAttribute
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", NullDisplayText = "FULL PAID"
public DateTime? NextDueDate
{
get { return return Receipt == null ? null ? Receipt.DueDate }
}
Upvotes: 2