Include ENUM description in LINQ results - asp.net-mvc

I have the following GROUP statement producing the results I am looking for.
However, I want to change line 4 below to "group s by s.ComplaintNatureTypeId.ToDescription()" so that the results are grouped by ENUM description rather than a numeric key value.
If I change the line I get the error "Method 'System.String ToDescription(System.Enum)' has no supported translation to SQL."
note: The ToDescription() is a Enum Extension method used to get description from enum.
var qry = from s in _db.Complaints
where s.Site.SiteDescription.Contains(searchTextSite)
&& (s.Raised >= startDate && s.Raised <= endDate)
group s by s.ComplaintNatureTypeId.ToString()
into grp
select new
{
Site = grp.Key,
Count = grp.Count()
};
return Json(qry.ToList(), JsonRequestBehavior.AllowGet);
The ENUM class :
using System.ComponentModel;
namespace Emas.Model.Enumerations
{
public enum ComplaintNatureType
{
[Description("- Please Select -")]
Blank = 0,
[Description("Letter")]
LE = 1,
[Description("eMail")]
EM = 2,
[Description("Verbal")]
VE = 3,
[Description("Other [see comments]")]
OT = 4,
}
}

You'll have to do the .ToDescription() in memory.
var qry = (from s in _db.Complaints
where s.Site.SiteDescription.Contains(searchTextSite)
&& (s.Raised >= startDate && s.Raised <= endDate)
group s by s.ComplaintNatureTypeId
into grp
select new
{
Site = grp.Key,
Count = grp.Count()
})
.ToList()
.Select(g => new
{
Site = g.Site.ToDescription(),
g.Count
});
return Json(qry, JsonRequestBehavior.AllowGet);

Related

GROUP BY LINQ ASP.NET MVC

Let's suppose we have a Linq query like this:
int companyID = Convert.ToInt32(((UserIdentity)User.Identity).CompanyId);
var stock = from i in _stockService.GetStock()
join ur in _inventoryService.GetInventory() on i.ProductID equals ur.Id
where ur.ComapnyId == companyID
select new StockVM
{
Product = ur.ItemName,
Quantity = i.Quantity,
BatchID = i.BatchID,
StockStatus = i.StockStatus,
MfgDate = i.MfgDate,
ExpDate = i.ExpDate,
};
Result
How to do a "Group By Product" with sum of Quantity in this linq query?
I need to only get max ExpDate firstOrDefault
try something like this:
int companyID = Convert.ToInt32(((UserIdentity)User.Identity).CompanyId);
var stock = from i in _stockService.GetStock()
join ur in _inventoryService.GetInventory() on i.ProductID equals ur.Id
where ur.ComapnyId == companyID
group new { Quantity = i.Quantity } by new { ur.ItemName } into g
select new { Product = g.Key, TotalQuantity = g.Sum() } ).ToList() ;
List<StockVM> _lst = new List<StockVM>();
foreach(var item in stock ){
StockVM row = new StockVM();
row.Product = item.ItemName;
//....
_lst.Add(row);
}

Date formatting from model is not working for datatype date

Hi I have on e query where I need to format date in MM/dd/YYYY format but it is but working
I have tried query as
var query = (from sr in db.StudentRequests
join r in db.Registrations on sr.RegistrationId equals r.RegistrationId
join cc in db.Campus on r.CampusId equals cc.CampusId
join c in db.Classes on sr.ClassId equals c.ClassId
from tc in db.TutorClasses.Where(t => t.ClassId == sr.ClassId).DefaultIfEmpty()
from srt in db.StudentRequestTimings.Where(s => s.StudentRequestId == sr.StudentRequestId).DefaultIfEmpty()
from tsr in db.TutorStudentRequests.Where(t => t.StudentRequestId == srt.StudentRequestId && t.TutorId == registrationid).DefaultIfEmpty()
from r1 in db.Registrations.Where(t => t.RegistrationId == tsr.TutorId).DefaultIfEmpty()
where tc.RegistrationId == registrationid
orderby sr.CreatedOn descending
select new
{
StatusId = tsr.StatusId == null ? 1 : tsr.StatusId,
Time = db.StudentRequestTimings.Where(p => p.StudentRequestId == sr.StudentRequestId)
.Select(p => p.FromTime.ToString() + "-" + p.ToTime +" " +p.Date+ "<br/>"),
}).ToList().GroupBy(p => new { p.StudentRequestId }).Select(g => g.First()).ToList();
Here at down you can see the time where p.date is there currently it is showing format as YYYY/MM/dd format but I want it to shown MM/dd/YYYY format
On Model side I had tried doing as
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public Nullable<System.DateTime> Date { get; set; }
but still not working
On controller side I had tried converting to format like below
Time = db.StudentRequestTimings.Where(p => p.StudentRequestId == sr.StudentRequestId).
Select(p => p.FromTime.ToString() + "-" + p.ToTime + " " + Convert.ToString(Convert.ToDateTime(p.Date).ToString("MM/dd/yyyy")) + "<br/>")
but in this case it is giving error as
Additional information: LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression.
I had also made use of converting to as enumerable
var model = query.AsEnumerable().Select(x => new TutorDashboard
{
Name = x.Name,
Phone = x.Phone,
Email = x.Email,
ProfilePicture = x.ProfilePicture,
TutorReviewRequestID = x.TutorReviewRequestID,
StudentRequestId = x.StudentRequestId,
RegistrationId = x.RegistrationId,
Location = x.Location,
PaymentMethod = x.PaymentMethod,
CreatedOn = x.CreatedOn,
AcceptedOn = x.AcceptedOn,
ClassName = x.ClassName,
CampusName = x.CampusName,
StripeId = x.StripeId,
AvailableMonth = Month,
AvailableYear = Year,
StatusId = x.StatusId == null ? 1 : x.StatusId,
Time = string.Join("", x.Time),
}).ToList().ToPagedList(page ?? 1, 10);
Change this
Convert.ToString(Convert.ToDateTime(p.Date).ToString("MM/dd/yyyy"))
to this:
p.Dated.HasValue? ((DateTime)p.Dated).ToString("dd/MM/yyyy") : ""
Your LINQ query is translated into SQL statements, and thus there are limitations to writing LINQ. Type conversations are included in those limitations.
However, you can do formatting elsewhere too like in View.
#Model.Date.ToString("MM/dd/YYYY");
If you don't want to bother, you can set your Culture to enUS and use .ToShortDateString() as well.
To use ToString("format_string") method from LINQ to Entities query, you need to materialize into IEnumerable object first with AsEnumerable() method:
var time = db.StudentRequestTimings.Where(p => p.StudentRequestId == sr.StudentRequestId)
.AsEnumerable() // insert this method
.Select(p => p.FromTime.ToString() + "-" + p.ToTime + " " + Convert.ToString(Convert.ToDateTime(p.Date).ToString("MM/dd/yyyy")) + "<br/>");
Then, pass IEnumerable<string> result to anonymous type part of second query:
var query = (from sr in db.StudentRequests
join r in db.Registrations on sr.RegistrationId equals r.RegistrationId
join cc in db.Campus on r.CampusId equals cc.CampusId
join c in db.Classes on sr.ClassId equals c.ClassId
from tc in db.TutorClasses.Where(t => t.ClassId == sr.ClassId).DefaultIfEmpty()
from srt in db.StudentRequestTimings.Where(s => s.StudentRequestId == sr.StudentRequestId).DefaultIfEmpty()
from tsr in db.TutorStudentRequests.Where(t => t.StudentRequestId == srt.StudentRequestId && t.TutorId == registrationid).DefaultIfEmpty()
from r1 in db.Registrations.Where(t => t.RegistrationId == tsr.TutorId).DefaultIfEmpty()
where tc.RegistrationId == registrationid
orderby sr.CreatedOn descending
select new
{
...
Time = time,
...
}).ToList().GroupBy(p => new { p.StudentRequestId }).Select(g => g.First()).ToList();
If you have large amount of stored data, besides materialization you can use either view formatting or using separate string property to display formatted date:
#* Display in view *#
#Model.Date.ToString("MM/dd/yyyy")
// using string property in viewmodel class for formatted DateTime
public string FormattedDate
{
get { return Date.ToString("MM/dd/yyyy"); }
}
NB: Entity Framework's LINQ to Entities tries to convert all query methods to SQL statements, currently ToString("format_string") has no SQL statement equivalent associated to that method unlike ToString() has (similar to CONVERT(VARCHAR(n), #Date)).
Similar issue:
How can I convert DateTime to String in Linq Query?

How to perform SUM operation in Entity Framework

I have a table.
create table tblCartItem(
pkCartItemId int primary key identity,
CartId int not null,
ProductId int not null,
Quantity int not null,
Price nvarchar(15)
)
and I want to perform sum opeartion on that like as
Select SUM(Price) from tblCartItem where CartId='107'
and I am trying to following code but its not working
ObjTempCart.CartTotal = (from c in db.tblCartItems where c.CartId == cartId select c.Price).Sum();
Any one help me to do this using Entity Framework.
I am using MVC 4 Razor.
May be You can use lambda Expression
var total=db.tblCartItems.Where(t=>t.CartId == cartId).Sum(i=>i.Price);
its working try this..
use Decimal.Parse to convert price.
ObjTempCart.CartTotal = db.tblCartItems.Where(t=>t.CartId == cartId).Select(i=>Decimal.Parse(i.Price)).Sum();
Finally I have a solution of that but its not exactly from Entity Framework, But its working...
private double CartItemTotalPrice(Int32 CartID)
{
List<string> pricelst = new List<string>();
pricelst = (from c in db.tblCartItems where c.CartId == CartID select c.Price).ToList();
double Total = 0;
if (pricelst != null)
{
for (int i = 0; i < pricelst.Count; i++)
{
Total += Convert.ToDouble(pricelst[i]);
}
}
return Total;
}
Decimal.parse not working, try Convert.toDouble
double total = _context.Projecao
.Where(p => p.Id == idProj)
.Select(i => Convert.ToDouble(i.ValorTotal)).Sum();

Create a custom list of Orders in NopCommerce

I'm trying to create a list of orders in a custom Controller in a NopCommerce/MVC application and i want the list to be sorted by creationDate and contain total orders for that date and convert these values to string format.
The thing is i don't want an ActionResult displaying a grid in the view like in Admin/Orders. All i want is a List of all paid orders between model.StartDate and model.EndDate that contains two parameters "CreationDateUtc" and TotalOrders". i simply just need a list containing the data of orders sorted by creationdate.
The if i choose StartDate 2014-03-29 and EndDate 2014-04-02 the output i want would look something like this:
List OrdersTotalList with parameters CreationDateUtc and TotalOrders
CreationDateUtc "2014-03-29"
TotalOrders "562"
CreationDateUtc "2014-03-30"
TotalOrders "485"
CreationDateUtc "2014-03-31"
TotalOrders "733"
CreationDateUtc "2014-04-01"
TotalOrders "729"
CreationDateUtc "2014-04-02"
TotalOrders "681
"
I'm trying to access the data by an implementations of OrderList from OrderController in my CustomController. Problem is this method always returns 10 objects when infact the total number of orders within this timespace is 58. When debugging Total = orders.TotalCount are actually showing 58 orders as one int value). Also a gridmodel is used here but i really don't need a gridmodel, i just need the data from the database:
public List OrderList(GridCommand command, OrderListModel model, OrderModel Omodel)
{
DateTime S = new DateTime(2014, 3, 29); //-- Dates for testing
DateTime E = new DateTime(2014, 4, 02);
model.StartDate = S;
model.EndDate = E;
DateTime? startDateValue = (model.StartDate == null) ? null
: (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.StartDate.Value, _dateTimeHelper.CurrentTimeZone);
DateTime? endDateValue = (model.EndDate == null) ? null
: (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.EndDate.Value, _dateTimeHelper.CurrentTimeZone).AddDays(1);
OrderStatus? orderStatus = model.OrderStatusId > 0 ? (OrderStatus?)(model.OrderStatusId) : null;
PaymentStatus? paymentStatus = model.PaymentStatusId > 0 ? (PaymentStatus?)(model.PaymentStatusId) : null;
ShippingStatus? shippingStatus = model.ShippingStatusId > 0 ? (ShippingStatus?)(model.ShippingStatusId) : null;
//load orders
var orders = _orderService.SearchOrders(startDateValue, endDateValue, orderStatus,
paymentStatus, shippingStatus, model.CustomerEmail, model.OrderGuid, command.Page - 1, command.PageSize);
var gridModel = new GridModel<OrderModel>
{
Data = orders.Select(x =>
{
var customerCurrency = _currencyService.GetCurrencyByCode(x.CustomerCurrencyCode);
var totalInCustomerCurrency = _currencyService.ConvertCurrency(x.OrderTotal, x.CurrencyRate);
return new OrderModel()
{
Id = x.Id,
OrderTotal = _priceFormatter.FormatPrice(totalInCustomerCurrency, true, customerCurrency),
OrderStatus = x.OrderStatus.GetLocalizedEnum(_localizationService, _workContext),
PaymentStatus = x.PaymentStatus.GetLocalizedEnum(_localizationService, _workContext),
ShippingStatus = x.ShippingStatus.GetLocalizedEnum(_localizationService, _workContext),
CreatedOn = _dateTimeHelper.ConvertToUserTime(x.CreatedOnUtc, DateTimeKind.Utc)
};
}),
Total = orders.TotalCount <-- Returns all orders (58) but as an integer
};
var reportSummary = _orderReportService.GetOrderAverageReportLine
(orderStatus, paymentStatus, shippingStatus, startDateValue, endDateValue, model.CustomerEmail);
var profit = _orderReportService.ProfitReport
(orderStatus, paymentStatus, shippingStatus, startDateValue, endDateValue, model.CustomerEmail);
var aggregator = new OrderModel()
{
aggregatorprofit = _priceFormatter.FormatPrice(profit, true, false),
aggregatortax = _priceFormatter.FormatPrice(reportSummary.SumTax, true, false),
aggregatortotal = _priceFormatter.FormatPrice(reportSummary.SumOrders, true, false)
//aggregatordates =
};
List<Order> TotalProductsSold = new List<Order>();
foreach (var o in orders)
{
TotalProductsSold.Add(o);
}
return TotalProductsSold.ToList(); //<-- returns 10 orders containing all order info
}
If i understand correct in order to archive this i have to first search through orders and if their PaymentStatus is Paid. Then create a List in the Method from above. A foreach loop could iterate through orders and add orders to the List, all though i need to specify i only want CreationDate and TotalOrders for that date as parameters in the List.
I know this isn't right but i emagine something similar. The thing is i need a list of order objects and not one object with one value:
List<OrderModel> OrdersTotalList = new List<OrderModel>();
foreach (var o in orders)
{
OrderModel OM = new OrderModel(OM.OrderTotal, OM.CreatedOn);
OrdersTotalList.Add(OM);
}
return OrdersTotalList; //--
Am i completely of or is this the right aproach? I was hoping someone more familiar with NopCommerce knows more about this.
Sorry for all the text
Thank you
Solved.
In order to get a full list of orders you can create a new constructor in IOrderService/OrderService that is of type List instead of IPagedList. The method used for searching orders are called "SearchOrders" and is of type IPagedList. IPagedList contains the property PageSize wich results in only 10 orders.
You can create a new method with same implementation as SearchOrders and change IPagedList to List, remove "int pageIndex" and "int pageSize".
Then use:
_orderService.YourNewConstructor(DateTime? startTime, DateTime? endTime,
OrderStatus? os, PaymentStatus? ps, ShippingStatus? ss, string billingEmail,
string orderGuid)
{
some code...
}
This will give you access to all orders.

Issue With Showing Distinct fields using Linq

var getAllProducts = _productService.GetAllProducts();
if (productstest.Count > 0)
{
model.idproduct.Add(new SelectListItem()
{
Value = "0",
Text = _localizationService.GetResource("Common.All")
});
foreach (var m in getAllProducts)
model.idproduct.Add(new SelectListItem()
{
Value = m.Id.ToString(),
**Text = m.Size.Distinct().ToString(),**
Selected = model.Pid == m.Id
});
}
public virtual IList<Product> GetAllProducts(bool showHidden = false)
{
var query = from p in _productRepository.Table
orderby p.Name
where (showHidden || p.Published) &&
!p.Deleted
select p;
var products = query.ToList();
return products;
}
The issue is even i tried to populate the select list with distinct size using: Text = m.Size.Distinct().ToString(), but it shows the duplicate for instance 100 products are of size 33 cm , the list will populate the dropdownlist in the view with 33cm occuring 100 times , I dont want to show 100 times , just want to show 1 time, Can any one assist me with this issue ?
Presumably you are only trying to show one product of each different size... if so initialising your getAllProducts variable like so will do the trick:
var getAllProducts = _productService.GetAllProducts().GroupBy(p => p.Size).Select(g => g.First());

Resources