c# Ordering Variable data using a drop down list - c#

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();

Related

Iterating through a list of view models and calculating values

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);
}

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;
}

Checking if item is null or if a table doesn't contain any matching data

I've got this query where I'm trying to check if there is an item in the table TruckItems that matches the string value in the variable tareTotal.
public QuoteResult GetTruckInformation(QuoteData data)
{
QuoteResult qr = null;
using (TruckDb db = new TruckDb())
{
var tareTotal = db.ChassisModel.Where(x => x.Id == data.ChassisId).FirstOrDefault();
var items = (from x in db.TruckItems where x.Model == tareTotal.Name select x); //Issue lies here
if (items.Any()) //Error here
{
var truckTareTotal = db.TruckItems.Where(x => x.Model == tareTotal.Name).FirstOrDefault().TareTotal;
var truckGVM = db.TruckItems.Where(x => x.Model == tareTotal.Name).FirstOrDefault().GVM;
var list = new QuoteResult
{
TareTotal = Convert.ToDouble(truckTareTotal),
GVM = Convert.ToDouble(truckGVM)
};
qr = list;
}
}
return qr;
}
I'm getting the error at if (items.Any()):
Non-static method requires a target.
I do not fully understand my problem and I can't find anything that might help me with my problem. Can someone please give me some pointers as to what I'm doing wrong with my variable items? Thank you!
EDIT:
Thanks to everyone for helping me! All of your coding works perfectly fine. I've found my issue and for some reason it has something to do with threading...
In my client side application I used the GetTruckInformation method in a combobox selection changed event and for some reason when it runs through that event, my server side application changes threads between all my statements, thus resulting in all of my data being null.
Here is my WPF/client side method just for show:
private async void cmbChassisModel_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
using (TruckServiceClient service = new TruckServiceClient())
{
QuoteData data = new QuoteData();
data.ChassisId = cmbChassisModel.GetDisplayItemId();
var items = await service.GetTruckInformationAsync(data);
if (items != null)
{
lblTareTotalAmount.Content = items.TareTotal;
lblGVMAmount.Content = items.GVM;
}
}
}
No one has to answer to this issue, I just wanted to let everyone know. :) I will try and figure out why this would happen. :)
Use a .ToList() on the items. Like this:
var items= db.TruckItems.Where(w=>w.Model == tareTotal.Name).ToList();
Otherwise you might run into troubles when executing .Any()
Edit:
Just for the sake of the expirment. Do this:
if(tareTotal==null)
throw new Exception("The tare total is null");
var items= db.TruckItems.Where(w=>w.Model == tareTotal.Name).ToList();
If no items match the db.ChassisModel.Where(x => x.Id == data.ChassisId) then tareTotal will be null.
Anyway, if you only want to check if db.TruckItems contains tareTotal.Name or not, use this. This also improve performance:
Change:
var items = (from x in db.TruckItems where x.Model == tareTotal.Name select x);
if (items.Any())
to:
if(db.TruckItems.Any(x => x.Model == tareTotal.Name))
Check this optimized method:
public QuoteResult GetTruckInformation(QuoteData data)
{
QuoteResult qr = null;
using (TruckDb db = new TruckDb())
{
var tareTotal = db.ChassisModel.Where(x => x.Id == data.ChassisId).FirstOrDefault();
if (tareTotal != null)
{
var item = db.TruckItems.Where(x => x.Model == tareTotal.Name).FirstOrDefault();
if (item != null)
{
var list = new QuoteResult
{
TareTotal = Convert.ToDouble(item.TareTotal),
GVM = Convert.ToDouble(item.GVM)
};
qr = list;
}
}
}
return qr;
}
Simple :
var hasItems = (from x in db.TruckItems where x.Model == tareTotal.Name select x).Any();
Will be tru if you have at least one item matching your condition.

db.SaveChanges() Exploding with Transaction Exception

The following method is causing the FIRST db.SaveChanges() to throw an exception:
(New transaction is not allowed because there are other threads running in the session.)
protected void btnInsertDependencies_Click(object sender, EventArgs e)
{
using (icmsEntities db = new icmsEntities())
{
var divisions = db.Divisions;
foreach (var division in divisions)
{
var dlc_sectors = db.Sectors.Where(s => s.Website.division_id == division.division_id).DistinctBy(s => s.name).ToList();
foreach (var sector in dlc_sectors)
{
dlc_Sector dlc_sector = new dlc_Sector
{
name = sector.name,
division_id = sector.Website.division_id
};
db.dlc_Sectors.AddObject(dlc_sector);
var dlc_products = db.Products.Where(p => p.Sectors
.Any(s => s.Website.division_id == dlc_sector.division_id && s.name == dlc_sector.name))
.DistinctBy(p => p.name).ToList();
foreach (var product in dlc_products.ToList())
{
var dlc_product = db.dlc_Products.SingleOrDefault(p => p.name == product.name);
if (dlc_product == null)
{
dlc_product = new dlc_Product { name = product.name };
db.dlc_Products.AddObject(dlc_product);
}
dlc_product.dlc_Sectors.Add(dlc_sector);
db.SaveChanges();
}
}
}
db.SaveChanges();
}
}
The first db.SaveChanges() is to make sure that a new product having the same name does not get inserted again.
How can I resolve this? Thanks in advance.
Worked for me:
var Local = db.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added)
.Where(es => es.Entity is dlc_Product).Select(es => es.Entity as dlc_Product);
var dlc_product = db.dlc_Products.SingleOrDefault(p => p.name == product.name)
?? Local.SingleOrDefault(p => p.name == product.name);
Thanks.
Not sure why this occurs, but the first SaveChanges() would not be necessary if you also checked the Local collection of db.dlc_Products:
foreach (var product in dlc_products.ToList())
{
var dlc_product = db.dlc_Products.SingleOrDefault(p => p.name == product.name)
?? db.dlc_Products.Local.SingleOrDefault(p => p.name == product.name);
...
}
New objects are added to the Local collection.
Note that db.dlc_Products.Join(db.dlc_Products.Local) looks more efficient, but it does not compile, and the other way around it queries the whole db.dlc_Products for each call.

Refactoring C# code - doing more within Linq

The code below is what I currently have and works fine. I feel that I could do more of the work I am doing in Linq instead of C# code.
Is there is anyone out there who can accomplish the same result with more Linq code and less C# code.
public List<Model.Question> GetSurveyQuestions(string type, int typeID)
{
using (eMTADataContext db = DataContextFactory.CreateContext())
{
List<Model.Question> questions = new List<Model.Question>();
List<Linq.Survey_Question> survey_questions;
List<Linq.Survey> surveys = db.Surveys
.Where(s => s.Type.Equals(type) && s.Type_ID.Equals(typeID))
.ToList();
if (surveys.Count > 0)
{
survey_questions = db.Survey_Questions
.Where(sq => sq.Survey_ID == surveys[0].ID).ToList();
foreach (Linq.Survey_Question sq in survey_questions)
{
Model.Question q = Mapper.ToBusinessObject(sq.Question);
q.Status = sq.Status;
questions.Add(q);
}
}
else
{
questions = null;
}
return questions;
}
}
Here is my Mapper function from my Entity to Biz Object
internal static Model.Question ToBusinessObject(Linq.Question q)
{
return new Model.Question
{
ID = q.ID,
Name = q.Name,
Text = q.Text,
Choices = ToBusinessObject(q.Question_Choices.ToList())
};
}
I want my mapper funciton to map the Question Status like so.
internal static Model.Question ToBusinessObject(Linq.Question q)
{
return new Model.Question
{
ID = q.ID,
Name = q.Name,
Text = q.Text,
Choices = ToBusinessObject(q.Question_Choices.ToList()),
Status = q.Survey_Questions[?].Status
};
}
? the issue is this function does not know which survey to pull the status from.
Instead of creating the biz object then setting the Status property in a foreach loop like so
foreach (Linq.Survey_Question sq in survey_questions)
{
Model.Question q = Mapper.ToBusinessObject(sq.Question);
q.Status = sq.Status;
questions.Add(q);
}
I would like to somehow filter the EntitySet<Survey_Question> in the q object above in the calling method, such that there would only be one item in the q.Survey_Questions[?] collection.
below is my database schema and business object schema
What I needed to do was setup a join.
public List<Model.Question> GetSurveyQuestions(string type, int typeID)
{
using (eMTADataContext db = DataContextFactory.CreateContext())
{
return db.Survey_Questions
.Where(s => s.Survey.Type.Equals(type) && s.Survey.Type_ID.Equals(typeID))
.Join(db.Questions,
sq => sq.Question_ID,
q => q.ID,
(sq, q) => Mapper.ToBusinessObject(q, sq.Status)).ToList();
}
}
And then overload my Mapper Function
internal static Model.Question ToBusinessObject(Linq.Question q, string status)
{
return new Model.Question
{
ID = q.ID,
Name = q.Name,
Text = q.Text,
Status = status,
Choices = ToBusinessObject(q.Question_Choices.ToList()),
};
}
from question in db.Survey_Questions
let surveys = (from s in db.Surveys
where string.Equals(s.Type, type, StringComparison.InvariantCultureIgnoreCase) &&
s.Type_ID == typeID)
where surveys.Any() &&
surveys.Contains(s => s.ID == question.ID)
select new Mapper.Question
{
ID = question.Id,
Name = question.Name,
Text = question.Text,
Choices = ToBusinessObject(question.Question_Choices.ToList()),
Status = question.Status
}
Does that get you on the right track?
Why are you duplicating all your classes? You could just extend the LINQ to SQL classes with your business logic - they are partial classes. This is somewhat against the purpose of an OR mapper - persisting business entities.

Categories

Resources