Iterating through a list of view models and calculating values - c#

I have an AddToCart action method which adds products to a cart via ajax, it basically works fine but sometimes (I cannot pinpoint it) e.g. I add a few products from one category, and then a few from another and the total doubles, so e.g. if I add 3 from one category, and then 1 from another it will be 4, and then again it will be 10! And then it will go on as normal.
Can you see what is wrong with this code?
public ActionResult AddToCart(string id)
{
List<CartVM> cartVMList = new List<CartVM>();
CartVM cartVM = new CartVM();
int productId = Int32.Parse(id);
int qty = 0;
decimal price2 = 0;
Db db = new Db();
var result = db.Products.FirstOrDefault(x => x.Id == productId);
decimal price = result.Price;
cartVM.ProductId = productId;
cartVM.Quantity = 1;
cartVM.Price = price;
if (Session["cart"] != null)
{
cartVMList = (List<CartVM>)Session["cart"];
var itemToEdit = cartVMList.FirstOrDefault(x => x.ProductId == productId);
if (itemToEdit == null)
{
cartVMList.Add(cartVM);
}
else
{
itemToEdit.Quantity++;
}
foreach (var item in cartVMList)
{
qty += item.Quantity;
price2 += item.Quantity * item.Price;
}
cartVM.Quantity = qty;
cartVM.Price = price2;
}
else
{
cartVMList.Add(cartVM);
Session["cart"] = cartVMList;
}
return PartialView(cartVM);
}
Basically the if (Session["cart"] != null) part is the meat of it and where the problem is I presume.

Your method contains a lot of unnecessary things and can be simplified a lot:
public ActionResult AddToCart(int productId)
{
// get a cart from session or create new
var cart = Session["cart"] as List<CartVM> ?? new List<CartVM>();
using(var db = new Db())
{
// get product in question
var product = db.Products
.FirstOrDefault(x => x.Id == productId)
// if this is unknown product, throw exception
if(product == null)
{
thrown new ArgumentException("Invalid product", nameof(productId));
}
// get existing line
var existingCartLine = cart
.FirstOrDefault(x => x.ProductId == productId);
// if there was no existing line, add a new one
if(existingCartLine == null)
{
cart.Add(new CartVM
{
ProductId = product.Id,
Quantity = 1,
Price = product.Price,
TotalPrice = product.Price
});
}
else
{
// otherwise modify existing line
existingCartLine.Quantity++;
existingCartLine.TotalPrice = cartLine.Price * cartLine.Quantity;
}
}
// save cart back in the session
Session["cart"] = cart;
// return view
return PartialView(cart);
}

Related

How to update a record using LINQ LAMBDA in my ASP.NET MVC 5 Project

I am new to entity framework and LINQ. I am stuck at an issue where I need to firstly check if the record already exists, if it exists then I need to update the record with column RESUMEID accordingly. If not then I need to add the record. I am able to add successfully but I don't know how to update the record in LINQ.
Below is my attempt:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ReferralViewModel viewModel)
{
var candidateId = User.Identity.GetUserId();
// I AM CONFUSED ABOUT BELOW STATEMENT
var IsDupeReferral = _context.Referrals
.Where(r => (r.CandidateId == candidateId)
&& (r.CompanyId == viewModel.CompanyId) && (r.SkillId == viewModel.SkillId))
.Select(r=>r.ReferralId).SingleOrDefault();
if(IsDupeReferral!=0)
{
//IF I FIND DUPE REFERRAL RECORD I WANT TO UPDATE SOME OF THE VALUES IN THAT
_context.Referrals.Where(r => r.ReferralId == IsDupeReferral).
AND UPDATE r.resumeId with viewModel.ResumeId // How to do this?
// NOT SURE ABOUT BELOW LINE EITHER
_context.SaveChanges();
}
else
{
// BELOW CODE IS WORKING FINE
var referral = new Referral
{
ReferralName = viewModel.ReferralName,
ResumeId = viewModel.ResumeId,
CandidateId = candidateId,
DegreeId = viewModel.DegreeId,
CoverLetterId = viewModel.CoverLetterId,
SkillId = viewModel.SkillId
};
if (!string.IsNullOrEmpty(viewModel.TempCompany))
{
var newCompany = new Company
{
CompanyName = viewModel.TempCompany
};
newCompany.Referrals.Add(referral);
_context.Companies.Add(newCompany); ;
}
else
{
referral.CompanyId = viewModel.CompanyId.Value;
_context.Referrals.Add(referral);
}
_context.SaveChanges();
}
return RedirectToAction("ReferralCenter");
}
Here's the solution
//IF I FIND DUPE REFERRAL RECORD I WANT TO UPDATE SOME OF THE VALUES IN THAT
var referral = _context.Referrals.FirstOrDefault(r => r.ReferralId == IsDupeReferral);
// AND UPDATE r.resumeId with viewModel.ResumeId
if (referral !=null) {
referral.resumeId = viewModel.ResumeId;
_context.Entry(referral).State = System.Data.EntityState.Modified;
_context.SaveChanges();
}
Actually, you don't need getting the IsDupeReferral and then request the record again. Try to combine your code as the following:
var referral = _context.Referrals
.Where(r => (r.CandidateId == candidateId)
&& (r.CompanyId == viewModel.CompanyId) && (r.SkillId == viewModel.SkillId)).SingleOrDefault();
if (referral !=null) {
referral.resumeId = viewModel.ResumeId;
_context.Entry(referral).State = System.Data.EntityState.Modified;
_context.SaveChanges();
}
else {
// add a new record
}
Referral referral = _context.Referrals.FirstOrDefault(r=> r.ReferralId = SomeId);
if(referral == null) // then referral does not exist - add it
{
referral = new Referral{
ReferralName = viewModel.ReferralName,
ResumeId = viewModel.ResumeId,
CandidateId = candidateId,
DegreeId = viewModel.DegreeId,
CoverLetterId = viewModel.CoverLetterId,
SkillId = viewModel.SkillId
};
_context.Referrals.Add(referral);
}
else // referral already exists - update its values
{
//make changes to referral
referral.ReferralName = viewModel.ReferralName;
referral.ResumeId = viewModel.ResumeId;
referral.CandidateId = candidateId;
referral.DegreeId = viewModel.DegreeId;
referral.CoverLetterId = viewModel.CoverLetterId;
referral.SkillId = viewModel.SkillId;
}
_context.SaveChanges(); //no matter added or updated - save the changes

How to Filter a Query On a One to Many Relationship via Linq

I have a Product and a Part Table. Here is the association:
Create Table Product
{
Id int,
Name nvarchar(max)
}
Create Table Part
{
Id int,
Name nvarchar (max),
ProductID int (foreign key to Product.Id),
SomeCategoryId int
}
Now, I want to return a list of Products with a List of Parts that only include a SomeCategoryId of 200.
Rules:
If a Part.SomeCategoryId <> 200, do not include the Part
If no Part.SomeCategoryId == 200 corresponding to the Product via Part.Product.Id, remove the entire Product.
How would make my code below more efficient?
prods = db.Products.OrderBy(o => o.Name).Select(pr => new ProductViewModel
{
Id = pr.Id,
Name = pr.Name,
Parts = pr.Parts.OrderBy(o => o.Name).Select(prt => new PartViewModel
{
Id = prt.Id,
Name = prt.Name,
SomeCategoryId = prt.SomeCategoryId
}).Where(w => w.SomeCategoryId == 200).ToList()
}).ToList();
foreach(var prod in prods)
{
var isSomeCategory = false;
foreach (var part in prod.Parts)
{
if (part.SomeCategoryId == 200)
{
isSomeCategory = !isSomeCategory;
}
}
if (isSomeCategory == false)
{
prods.Remove(prod);
}
}
what about...
prods = db.Products.Where(pr => pr.Parts.Any(p => p.SomeCategoryId == 200)).OrderBy(o => o.Name).Select(pr => new ProductViewModel
{
Id = pr.Id,
Name = pr.Name,
Parts = pr.Parts.OrderBy(o => o.Name).Select(prt => new PartViewModel
{
Id = prt.Id,
Name = prt.Name,
SomeCategoryId = prt.SomeCategoryId
}).Where(w => w.SomeCategoryId == 200).ToList()
}).ToList();

Not Returning properly

I was trying to get employee list which not already available in another list. but im getting only first element from array list.
ex : if i try EmployeeId = new int[2] {5, 2}; the list excluding only '5'. So please help me correct my below code.
public JsonResult GetEmployees(int[] EmployeeId)
{
var dbs = new dbContext();
if (EmployeeId != null)
{
foreach (var emp in EmployeeId)
{
var EmpList = dbs.Employees.Select(e => new
{
EmployeeId = e.EmployeeId,
Name = e.EmployeeName,
Job = e.Job.JobName,
Currency = e.Currency.CurrencyName,
Amount = e.Amount
}).Where(o => o.EmployeeId != emp);
return Json(EmpList, JsonRequestBehavior.AllowGet);
}
}
return null
}
Try this :
var employeeList = dbs.Employees.
.Where(e => EmployeeId.All(x=> x != e.EmployeeId))
.Select(e => new
{
EmployeeId = e.EmployeeId,
Name = e.EmployeeName,
Job = e.Job.JobName,
Currency = e.Currency.CurrencyName,
Amount = e.Amount
});
return Json(EmpList, JsonRequestBehavior.AllowGet);
}
Have you tried stepping through your code?
Your foreach iterates over your EmployeeId array.
Since you have a return statement in your foreach it exits the function at that point and it only uses the first element of your array.
You need something like this:
public JsonResult GetEmployees(int[] EmployeeId)
{
var dbs = new dbContext();
if (EmployeeId != null)
{
var EmpList = dbs.Employees.Where(EmployeeId.Contains(e.EmployeeId))
.Select(e => new
{
EmployeeId = e.EmployeeId,
Name = e.EmployeeName,
Job = e.Job.JobName,
Currency = e.Currency.CurrencyName,
Amount = e.Amount
}).Where(o => o.EmployeeId != emp);
return Json(EmpList, JsonRequestBehavior.AllowGet);
}
return null;
}

Save the data in the list to another table

[HttpPost]
public ActionResult AddVotes(List<CampaignManager_tbl> list, int events_category_id, int candidates_info_id) {
if (ModelState.IsValid)
{
var events = db.Events_Info_tbl.Where(x => x.is_active == true).FirstOrDefault();
var username = User.Identity.Name;
var getID = db.Account_Info_tbl.Where(x => x.username == username).FirstOrDefault();
foreach (var i in list)
{
Votes_tbl vote = new Votes_tbl();
vote.candidates_info_id = i.candidates_info_id;
vote.C_voters_info_id = getID.account_info_id;
vote.events_info_id = events.events_info_id;
vote.events_category_id = i.events_category_id;
vote.votes_history = true;
db.Votes_tbl.Add(vote);
}
db.SaveChanges();
RedirectToAction("Index");
}
return View(list);
}
This is my code where I am going to save the data in the list into the database but it is not working. List<CampaignManager_tbl> List contains the data to be saved in the Votes_tbl.
What's wrong with this code? How I am gonna save this data?
Save your data outside the loop.
[HttpPost]
public ActionResult AddVotes(List<CampaignManager_tbl> list, int category_id, int candidates_info_id) {
if (ModelState.IsValid)
{
var events = db.Events_Info_tbl.Where(x => x.is_active == true).FirstOrDefault();
var username = User.Identity.Name;
var getID = db.Account_Info_tbl.Where(x => x.username == username).FirstOrDefault();
foreach (var i in list)
{
Votes_tbl vote = new Votes_tbl();
vote.candidates_info_id = i.candidates_info_id;
vote.C_voters_info_id = getID.account_info_id;
vote.events_info_id = events.events_info_id;
vote.events_category_id = category_id;
vote.votes_history = true;
db.Voters_Info_tbl.Add(vote);
}
db.SaveChanges();
RedirectToAction("Index");
}
return View(list);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddVotes(List<CampaignManager_tbl> list)
{
if (ModelState.IsValid)
{
var events = db.Events_Info_tbl.Where(x => x.is_active == true).FirstOrDefault();
var username = User.Identity.Name;
var getID = db.Account_Info_tbl.Where(x => x.username == username).FirstOrDefault();
foreach (var i in list)
{
int val = 1;
bool y = Convert.ToBoolean(val);
if (i.isSelected == y) {
Votes_tbl vote = new Votes_tbl();
vote.candidates_info_id = i.candidates_info_id;
vote.C_voters_info_id = getID.account_info_id;
vote.events_info_id = events.events_info_id;
vote.events_category_id = i.events_category_id;
vote.votes_history = true;
db.Votes_tbl.Add(vote);
}
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(list);
}
I've come up to this solution but anyway thanks for giving advices. It helps a lot. Thank You.

c# Ordering Variable data using a drop down list

I am currently stuck on a small problem.
I have a List View which displays products and I am looking to include a drop down list, with a filter button which when pressed will order the products by high-low price or low-high.
Here is my code.
protected void LB_Filter_Click(object sender, EventArgs e)
{
using (DataClasses_ECDataContext db = new DataClasses_ECDataContext())
{
DT_Product Pro = db.DT_Products.SingleOrDefault(x => x.ProductID == int.Parse(ViewState["ProductID"].ToString()));
var product = from x in db.DT_Products
where x.RangeID == Pro.RangeID
select new
{
x.ProductName,
x.ProductID,
x.Sale_Price,
Link = RouteTable.Routes.GetVirtualPath(null, "Product-by-tag", codesnippets.RouteLink(x.ProductID, x.ProductName, 'p')).VirtualPath,
};
if (DDL_Order.SelectedIndex == 0)
{
product.OrderByDescending(v => v.Sale_Price);
}
else if (DDL_Order.SelectedIndex == 1)
{
product.OrderBy(v => v.Sale_Price);
}
LV_Products.DataSource = product;
LV_Products.DataBind();
}
}
Any Help would be fantastic,
Thanks!
You need to execute the results by converting it to list to get the expected output, like this:
List<DT_Product> products = new List<DT_Product>();
if (DDL_Order.SelectedIndex == 0) {
products = product.OrderByDescending(v => v.Sale_Price).ToList();
} else if (DDL_Order.SelectedIndex == 1) {
products = product.OrderBy(v => v.Sale_Price).ToList();
}
LV_Products.DataSource = products;
LV_Product.DataTextField = "ProductName";
LV_Product.DataValueField = "ProductID";
LV_Products.DataBind();
Are you missing this?
LV_Products.DataSource = product;
LV_Product.DataTextField="ProductName";
LV_Product.DataValueField="ProductID";
LV_Products.DataBind();

Categories

Resources