Select distinct categories from database - c#

I am designing the back end of an app and I want to get distinct categories from the database.I am using the following query:
var categories = from source in vm.Sources select source.Source_Category.ToList().Distinct();
And my model has four fields namely (Source_Name,Source_Link,Source_Subscribed,Source_Category)
The model contains 4 entries in total,two belong to category "News" and other two belong to "Science".But using the above query I'm getting all four entries,Ideally it should return only two items.Where am I going wrong?

You are lacking of the parenthesis, it should be:
var categories = (from source in vm.Sources select source.Source_Category)
.Distinct();
For more readable, I would prefer using lambda:
var categories = vm.Sources.Select(s => s.Source_Category)
.Distinct();

Related

Equivalent of INNER JOIN ... WHERE in NHibernate

I have class Category that contains a List<Subcategory>.
Using LINQ (preferrably), I want to get all Categoriess but filter their Subcategories such that the resulting query would look like:
SELECT * FROM categories
LEFT JOIN subcategories ON subcategories.category_Id = categories.id WHERE subcategories.Retired = false
I have tried:
session.QueryOver<Category>()
.Left.JoinQueryOver(c => c.Subcategories, () => subcategoryAlis, s => !s.Retired)
.List<Category>())
And a few other hacky looking tricks but I can't seem to get the results I need. The above query produces completely useless results with the same entries appearing multiple times and many missing.
It's been a while since I've used NHibernate, but I would do it with some dedicated DTO classes for converting to Json, not directly from the entities. I think something along the lines of the following linq query should work:
from c in session.Query<Category>
select new CategoryDto {
Name = c.Name, //and other properties
SubCategories = c.SubCategories
.Where(sc => !sc.Retired)
.Select(sc => new SubCategoryDto { ... })
.ToList()
}

LINQ contains between 2 lists

I have a string List and a supplier List<supplier>.
string list contains some searched items and supplier list contains a list of supplier object.
Now I need to find all the supplier names that matches with any of the items in the string List<string>.
this is one of my failed attempts..
var query = some join with the supplier table.
query = query.where(k=>stringlist.contains(k.companyname)).select (...).tolist();
any idea how to do that??
EDIT:
May be my question is not clear enough...I need to find a list of suppliers(not only names,the whole object) where suppliers names matches with the any items in the string list.
If I do
query = query.where(k=>k.companyname.contains("any_string")).select (...).tolist();
it works. but this is not my requirement.
My requirement is a list of string not a single string.
Following query will return distinct suppliers names which exist in list of names:
suppliers.Where(s => stringlist.Contains(s.CompanyName))
.Select(s => s.CompanyName) // remove if you need whole supplier object
.Distinct();
Generated SQL query will look like:
SELECT DISTINCT [t0].[FCompanyName]
FROM [dbo].[Supplier] AS [t0]
WHERE [t0].[CompanyName] IN (#p0, #p1, #p2)
BTW consider to use better names, e.g. companyNames instead of stringlist
You could use Intersect for this (for just matching names):
var suppliersInBothLists = supplierNames
.Intersect(supplierObjects.Select(s => s.CompanyName));
After your EDIT, for suppliers (not just names):
var suppliers = supplierObjects.Where(s => supplierNames.Contains(s.CompanyName));
var matches = yourList.Where(x => stringList.Contains(x.CompanyName)).Select(x => x.CompanyName).ToList();
Either use a join as Tim suggested or you could just use a HashSet directly. This is much more efficient that using .Contains on a List as in some of the other answers.
var stringSet = new HashSet(stringList);
var result = query.Where(q => stringSet.Contains(q.Name));

Splitting Linq List by grouping

for reporting purposes i wanna split a list of purchase orders into multiple lists. One list for each purchase address. I know it's possible to group the list by purchase address, but my question is how to split the list by this purchase address into multiple lists and use these multiple list to create individual reporting files.
code:
(from o in orders
group o by new {field1, field2, field3, field4} into og
orderby og.Key.field1
select new ViewClass
{
purchaseAddress = og.Key.field1,
product = og.key.field2,
count = og.count
}).ToList()
question: how to split above list into multiple lists for each purchaseAddress?
There's a built-in function that I think does what you want. If I assume that your code is assigned to a variable called query then you can write this:
ILookup<string, ViewClass> queryLists = query.ToLookup(x => x.purchaseAddress);
This essentially creates a list of lists that you access like a dictionary, except that each value is a list of zero or more values. Something like:
IEnumerable<ViewClass> someList = queryLists["Some Address"];
Just turn each group into a List.
select new ViewClass
{
purchaseAddress = og.Key.field1,
product = og.key.field2,
count = og.count,
List = og.ToList()
}).ToList();
Oh, your grouping is one way for entities and another way for pages... just regroup.
List<ViewClass> classes = (
from o in orders
group o by new {field1, field2, field3, field4} into og
orderby og.Key.field1
select new ViewClass
{
purchaseAddress = og.Key.field1,
product = og.key.field2,
count = og.count
}).ToList();
List<List<ViewClass>> regrouped = (
from c in classes
group c by c.purchaseAddress into g
select g.ToList()
).ToList();
Another simple built-in function that you can use is the GroupBy function. It does a similar job as the ToLookup but it means that your new list is IQuerable, not like a dictionary and a few other things (see this article for a good breakdown)
var newList = orders.GroupBy(x => x.field1);
This will return a list of lists grouped by the field(s) you specify.

LINQ Many to Many With In or Contains Clause (and a twist)

I have a many to many table structure called PropertyPets. It contains a dual primary key consisting of a PropertyID (from a Property table) and one or more PetIDs (from a Pet table).
Next I have a search screen where people can multiple select pets from a jquery multiple select dropdown. Let's say somebody selects Dogs and Cats.
Now, I want to be able to return all properties that contain BOTH dogs and cats in the many to many table, PropertyPets. I'm trying to do this with Linq to Sql.
I've looked at the Contains clause, but it doesn't seem to work for my requirement:
var result = properties.Where(p => search.PetType.Contains(p.PropertyPets));
Here, search.PetType is an int[] array of the Id's for Dog and Cat (which were selected in the multiple select drop down). The problem is first, Contains requires a string not an IEnumerable of type PropertyPet. And second, I need to find the properties that have BOTH dogs and cats and not just simply containing one or the other.
Thank you for any pointers.
You can do this using a nested where clause.
You need to filter p.PropertyPets using contains - return all rows where PetID is in search.PetType.
Then only return rows from properties where all search id's have been found - eg number of rows >= number of serach id's
All together:
var result = from p in properties
where p.PropertyPets.Where(c => search.PetType.Contains(c.PetID)).Count() >= search.PetType.Count()
select p;
For the part where Contains requires a string would not be true, Contains should require an int if your search.PetType is int[]. That means that you need to "convert" p.PropertyPets into an int. To convert p.PropertyPets to IEnumerable<int> you need to select the PropertyID field: p.PropertyPets.Select(propertyPet => propertyPet.PropertyID), but that won't get you a single int as required but a whole bunch. (.First() would give you one int but not solve your problem.
What you really want to do is
var result = properties.Where(p =>
search.PetType.Except(p.PropertyPets.Select(propertyPet =>
propertyPet.PropertyID)).Count() == 0);
But Except is not available in LINQ2SQL.
The best option I can find is to apply Contains for each item in search.PetType.
Something like this:
var result = properties;
foreach(var petType in search.PetType)
{
result = from p in result
where p.PropertyPets.Select(propertyPet =>
propertyPet.PropertyID).Contains(petType)
select p;
}

linq to sql LoadWith limiting fields returned

Is there a way to use LoadWith but specify the fields that are returned?
For example, if I have two tables 1) Products 2) Categories
and do something like
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Products>(d => d.Categories);
db.LoadOptions = dlo;
MyDataContext db = new MyDataContext();
var result = from d in db.Products
select d;
when i check the query in profiler i see that ALL the rows from the Categories table are being returned. All I really need is the "Name" field.
I know I can rewrite the query using joins but I need to return the result set as a "Product" data type which is why I am using LoadWith.
No that's not possible with LoadWith.
You could try with a nested query in the projection, though that will be slow: 1 query per parent (so 1 query for the related category per product loaded).
You can use a projection, but you need to deal with anynomus types after that
select new {Order = order, ProductName = order.Product.Name,
CustomerName = order.Customer.Name,
OrderType = order.OrderType.Name } // etc

Categories

Resources