I have two tables deal_outlet and vendors_outlet. I am trying to compare a list of outlet_id from deal_outlet table to vendor table but .contain method shows error has some invalid arguments. I really don't understand problem in this code.
public ActionResult Detail_of_deal(int id)
{
var d1 = db.deal_outlet.Where(x => x.outlet_id==id).ToList();
f_model.model4 = db.vendors_outlet.Where(x =>d1.Contains(x.outlet_id)).ToList();
var d = obj.detail_of_image(id,ref model);
return View(f_model);
}
Depending on the goal of the code you could try the following:
public ActionResult Detail_of_deal(int id)
{
var d1 = db.deal_outlet.Where(x => x.outlet_id==id).ToList();
f_model.model4 = db.vendors_outlet.AsEnumerable().Select(x => d1.Contains(x.outlet_id)).ToList();
var d = obj.detail_of_image(id,ref model);
return View(f_model);
}
That should make f_model.model4 a list of all the vendors_outlets that have a matching deal_outlet.id
The Linq Contains method returns true if the list contains the item passed in. You are asking to see if a list of deal_outlet objects contains an int, which obviously it won't.
Instead of projecting a collection of deal_outlets, project a list of integers:
var d1 = db.deal_outlet.Where(x => x.outlet_id==id).Select(x => x.outlet_id);
f_model.model4 = db.vendors_outlet.Where(x =>d1.Contains(x.outlet_id)).ToList();
But logically, that's the same as:
f_model.model4 = db.vendors_outlet.Where(x =>x.outlet_i==id)).ToList();
So it's not clear what you're trying to do.
EDIT
Based on your comments, I believe these are the queries you want:
i am trying to fetch list of outlet_id from deal_outlet table where deal_id equal to id,
var d1 = db.deal_outlet.Where(x => x.deal_id==id).ToList();
Now want to compare this list to vendor_outlet table and fetch those rows where outlet_id from deal_outlet table equals to outlet_id in vendor_outlet table
Get a list of ID's to match:
var ids = d1.Select(x => x.outlet_id).ToList();
And use Contains to see if the list contains any of the IDs from the related table:
f_model.model4 = db.vendors_outlet.Where(vo => ids.Contains(vo.outlet_id))
.ToList();
Related
I have two lists rtrn and Zipcodes
rtnr items have a Utility field. I need to return a subset of rtrn where rtrn.Utility exists in field1 or filed2 or field3 of zipocode item
Get the unique utilities from this zipcodes fileds 1-3
DbSet<Utility> utilities;
DbSet<Zipcodes> zipcodes;
var uniqeUtilitiesInZipcodes = zipcodes.Select(x => x.Field1).ToList();
uniqeUtilitiesInZipcodes.AddRange(zipcodes.Select(x => x.Field2).ToList());
uniqeUtilitiesInZipcodes.AddRange(zipcodes.Select(x => x.Field3).ToList());
uniqeUtilitiesInZipcodes = uniqeUtilitiesInZipcodes.Distinct().ToList();
Intersect unique utilities with zipcodes
uniqeUtilitiesInZipcodes = uniqeUtilitiesInZipcodes.Distinct().ToList();
var zipcodesWhereUtilityExistsInAnyUtiltyField = utilities.Intersect(uniqeUtilitiesInZipcodes).ToList();
I have "Products table" with following fields
PID int,
product_name varchar(),
product_price int
"Cart table" with following fields
cart_ID
user_id
PID
So I want to display cart items of logged in user
For example if user_ID=100 is logged in , then only his cart items should be displayed to him, with all the product details.
Am using asp.net with entity framework
public ActionResult Cart()
{
Products pro = new Products();
Cart cart =new Cart();
var productID = db.cartDetails.Where(pid => pid.productId == cart.productId && cart.user_id == session["user_ID"]);
return View(db.productsDetails.Where(pid => pid.productId == productID));
}
Now problem arises, ProductID being var type I cannot compare it with pid => pid.productid.
What I want to do is first get all the product_id's of user from cart table by comparing uid_id (Logged in user) with user_id in cart table, then displaying product details of those product_id's from product Table. So obviously I need to store multiple product_id's,so that i can populate their data on the cart page.
The LINQ expression db.cartDetails.Where(pid=>pid.productId==cart.productId && cart.user_id==session["user_ID"]) would return a collection of cartDetails and not the productId. You must use select to fetch the columns you need, something like this
var productIDs = db.cartDetails
.Where(pid => pid.productId == cart.productId && cart.user_id == session["user_ID"])
.Select(cd => cd.productId)
.ToList();
This would return you a List of productIds. (If you wish to get only one productId, you could use SingleOrDefault or FirstOrDefault depending on your scenario like db.cartDetails.SingleOrDefault(pid => ...).productId).
Also note that you could have used int type for productId instead of using var if you were expecting an integer. Now you are getting a collection type IQueryable<cardDetails> being assigned to productId.
Next you cannot use an equality operator for the returned List anymore, you should check if this list contains the productId from productDetails, something like this:
return View(db.productsDetails.Where(pid => productIDs.Contains(pid.productId)));
Couldn't test this code, but the basic idea is here.
One last thing, consider using a join between the two tables: https://msdn.microsoft.com/en-us/library/bb311040.aspx
Did this and now my cart is working fine
public ActionResult Cart()
List<int> productIDs = new List<int>();
productIDs = db.cartDetails.Where(ch => ch.userId ==12).Select(cd => cd.productId).ToList() ;
List<Products> pDetails = new List<Products>();
for(int i=0;i<productIDs.Count;i++)
{
pDetails.Add(db.productsDetails.Find(productIDs[i]));
}
return View(pDetails);
I've been racking by brain all night (again) looking to get the total count of each set of unique items in a list. I was able to get the unique list items. But I can't seem to figure out how to get the count of each group of unique items. Please tell me if this makes sense. Below's my code:
List<string> categories = new List<string>();
foreach (var item in Model)
{
categories.Add(item.Category);
}
IEnumerable<string> distinctCategories = categories.Distinct();
foreach (string category in distinctCategories)
{
#category #category.Count()
}
As you can see, I have a link displayed for each unique item in my Model's "Category" property (Item.Category). Where you see the category count at the end of the link it actually displays the number of characters in the category (such as the number 5 for the category "Rings"). But I really want the number to represent the number of times the category "Rings", for example, is found in the Model's Categories property.
Please help
To get the count, you need to use a GroupBy instead of Distinct:
var distinctCategories =
categories.GroupBy(x => x)
.Select(g => new { Name = g.Key, ItemsCount = g.Count() });
foreach (var category in distinctCategories)
{
#category.Name #category.ItemsCount
}
I'm designing an interface where the user can join a publicaiton to a keyword, and when they do, I want to suggest other keywords that commonly occur in tandem with the selected keyword. The trick is getting the frequency of correlation alongside the properties of the suggested keywords.
The Keyword type (EF) has these fields:
int Id
string Text
string UrlString
...and a many-to-many relation to a Publications entity-set.
I'm almost there. With :
var overlappedKeywords =
selectedKeyword.Publications.SelectMany(p => p.Keywords).ToList();
Here I get something very useful: a flattened list of keywords, each duplicated in the list however many times it appears in tandem with selectedKeyword.
The remaining Challenge:
So I want to get a count of the number of times each keyword appears in this list, and project the distinct keyword entities onto a new type, called KeywordCounts, having the same fields as Keyword but with one extra field: int PublicationsCount, into which I will populate the count of each Keyword within overlappedKeywords. How can I do this??
So far I've tried 2 approaches:
var keywordCounts = overlappingKeywords
.Select(oc => new KeywordCount
{
KeywordId = oc.Id,
Text = oc.Text,
UrlString = oc.UrlString,
PublicationsCount = overlappingKeywords.Count(ok2 => ok2.Id == oc.Id)
})
.Distinct();
...PublicationsCount is getting populated correctly, but Distinct isn't working here. (must I create an EqualityComarer for this? Why doesn't the default EqualityComarer work?)
var keywordCounts = overlappingKeywords
.GroupBy(o => o.Id)
.Select(c => new KeywordCount
{
Id = ???
Text = ???
UrlString = ???
PublicationsCount = ???
})
I'm not very clear on GroupBy. I don't seem to have any access to 'o' in the Select, and c isn't comping up with any properties of Keyword
UPDATE
My first approach would work with a simple EqualityComparer passed into .Distinct() :
class KeywordEqualityComparer : IEqualityComparer<KeywordCount>
{
public bool Equals(KeywordCount k1, KeywordCount k2)
{
return k1.KeywordId== k2.KeywordId;
}
public int GetHashCode(KeywordCount k)
{
return k.KeywordId.GetHashCode();
}
}
...but Slauma's answer is preferable (and accepted) because it does not require this. I'm still stumped as to what the default EqualityComparer would be for an EF entity instance -- wouldn't it just compare based on primary ids, as I did above here?
You second try is the better approach. I think the complete code would be:
var keywordCounts = overlappingKeywords
.GroupBy(o => o.Id)
.Select(c => new KeywordCount
{
Id = c.Key,
Text = c.Select(x => x.Text).FirstOrDefault(),
UrlString = c.Select(x => x.UrlString).FirstOrDefault(),
PublicationsCount = c.Count()
})
.ToList();
This is LINQ to Objects, I guess, because there doesn't seem to be a EF context involved but an object overlappingKeywords, so the grouping happens in memory, not in the database.
Given a table of order items (OrderItems) that relates to a table of orders (Orders), which in turn relates to a table of users (Users), is it possible to retrieve all the OrderItems and group them into a dictionary by OrderId with just one query? ie. without performing an iteration over either the OrderItems result set or performing a query for each order.
Desired controller pseudo-code
Dictionary<int,IEnumerable<OrderItem>> OrderItems = DataContext.OrderItems.ToDictionary(Key => oi.OrderId, Value => oi.ToList());
Desired usage:
IEnumerable<OrderItem> currentOrderItems = OrderItems[123]; // where 123 is OrderId
Current Method
In my Controller I presently retrieve a user's orders and order items to pass to the Orders view:
ViewData["Orders"] = (from o in orders
where o.UserId equals CurrentUserId
orderby o.DateCreated descending)
.ToList();
ViewData["OrderItems"] = (from oi in DataContext.OrderItems
join o in DataContext.Orders
on oi.OrderId equals o.OrderId
where o.UserId equals CurrentUserId
select oi)
.ToList();
Then in my view, I retrieve all order items:
IEnumerable<OrderItem> orderItems = ViewData["OrderItems"] as IEnumerable<OrderItem>;
and use LINQ to group and display each order's order items:
IEnumerable<OrderItem> currentOrderItems = orderItems.Where(
i => i.OrderId == order.OrderId
);
This is fairly efficient as only two queries are passed to the database and some processing is done in the view. But ideally, this should be done in the controller.
Solved it! With ToLookup(...)
ViewData["OrderItems"] = (from oi in DataContext.OrderItems
join o in DataContext.Orders
on oi.OrderId equals o.OrderId
where o.UserId == UserId
select oi).ToLookup(oi => oi.OrderId, oi => oi);
And in my view:
ILookup<int,OrderItem> orderItems = ViewData["OrderItems"] as ILookup<int,OrderItem>;
foreach (Order order in orders)
{
DisplayOrder(order);
// Now display this order's items:
foreach(OrderItem item in orderItems[order.OrderId])
{
DisplayOrderItem(item);
}
}
A trace shows only one query to create the lookup.
Looks like I'm making a habit out of answering my own questions...
I think your best bet is to create a method that accepts a lambda for the key and a list to be inserted into the dictionary and then simply enumerates the list and adds to the dictionary using the key provided in the lambda. The method could be an Extension Method of IDictionary and let's call it say, AddRangeWithKeyType()