Poor wording I know, so I will be clear here..
I have
List<int> relevantIDs; //self explanitory
Now I am trying to select a list of objects from the database where their IDs exist within the list above... I cant seem to figure out the linq...
dbContext.objs.where(x => x.id ....).toList();
//I cant figure out the .... i was thinking there was an "in" but got no where...
can someone point me to an article or provide me a sample that will accomplish what I need. The list would be too big to just retrieve them all then filter down.... and hitting the database repeatedly would be not optimal in this case...
You want to find the IDs from the database that are contained within your collection of "relevant IDs", so this should work:
dbContext.objs.Where(x => relevantIDs.Contains(x.id)).ToList();
You are looking for Contains
dbContext.objs.Where(x => relevantIDs.Contains(x.id)).ToList();
This will be translated as IN clause into SQL.
Related
I'm having some trouble optimizing this query.
This is to filter out users that have a particular set of skills.
These skills are sent to the server in the form of a list of their IDs, which are GUIDs.
unfortunately I cannot just get the user as easily as I would like because the last person working on this placed this in a SQL view.
This is where we try and find all users with all skills selected.
skillIDs is the list of GUIDs
Here is what it looks like
myview.Where(view => skillIDs.All(skill => view.User.Skills.Any(s => s.ID == skill)))
Other things we have tried
myView.Where(view => !skillIDs.Except(view.User.Skills.Select(skill => skill.ID).Any()))
myview.Where(view => skillIDs.All(skill => view.User.Skills.Select(s => s.ID).contains(skill)))
I realize the way it is working is highly inefficient and yes, we are paginating the results, but not until after this query. What I believe is happening is it is executing the query here rather than waiting for the .skip(0).Take(10).tolist() which is when it should execute. Right now it takes 45 seconds for this to work.When it's not trying to execute the query above it's less than a second so I know this is the culprit.
In this case playing with different variations of LINQ won't make a difference as the issue is likely in the backend table indexing, not in how you create a LINQ statement. You really have two options:
Index the backend table as the view will be able to use index on the table if it needs
Index a view directly. The definition of an indexed view must be deterministic. MSDN
CREATE UNIQUE CLUSTERED INDEX IDX_V1
ON myview (skillid);
GO
I am trying to find the fastest way to know if a number of documents exist in MongoDB. I don't need the documents themselves, just a confirmation of their existence.
Let's assume I have this list:
var L = new List<string> {"1", "3", "A"};
and I want to find if these documents exist.
One way to do is it like this (syntax may be a bit off since I'm trying this from memory, but the idea is there):
find(Query.In(_ => _._id, L));
and it works, but it returns all the documents as well, which is a waste of time
So, I get only the ids, through projection:
find(Query.In(_ => _._id, L)).Project(Projection.Expression(_ => _._id));
and this works very well and returns me a list of existing ids.
The question is: is it efficient to find/project? or is there a faster way to achieve the same?
(bonus question: how can I do query.in with the fluent syntax? :))
The way you are doing it is, on my opiniion ok. I would do the same. Project step is executing on server, so you don't get the complete documents, just Ids, it's exact that you want.
You could do the same query with fluent syntax, it's just (i assume your collection in the collection variable):
collection.Find(_=>L.Contains(_._id)).Project(_=>_.Id).ToList();
I have a list of prices that is based off of products which are in categories. I need to make sure those prices of products in sub-categories do not show up in this list, but they are. Sub-categories and categories are in the same table in the db, the only difference is that a sub-category will have a parent ID to show that it's a child.
I have these 2 LINQ statements that I need to tie together somehow and I can't get it right. Maybe I am not trying to do this the right way, but I'm not very experienced with LINQ yet and I haven't been able to find much help online.
To be clear, this is not for removing duplicates, I don't have that problem, I just need to prevent some of the results from showing up.
var subCategories = siteCategory.SiteSubCategories.Where(x => x.Active);
string lowestPrice = siteCategory.SiteProducts.Min(x => x.Price).ToString();
I have tried to do the following
string lowestPrice = siteCategory.SiteProducts.Where(!subCategories).Min(x => x.Price).ToString();
but I get an error saying Operator '!' cannot be applied to operand of type 'IEnumerable'
I've also tried multiple other combinations of linq statements, too many to list, so I just listed the one that I tried which made the most sense to me.
Can someone help me figure out what I am doing wrong? Thanks in advance.
You should use a lambda with .Where. That part of the code should be something like
siteCategory.SiteProducts
.Where(product => !subCategories.contains(product.Category))
.Min(x => x.Price).ToString()
with the appropriate way of getting the category of a product. I guessed at product.Category, you'll need to update that piece yourself.
I don't know the details of how your data is modeled, but assuming that Product has a Category property. And that Category has a ParentId nullable property, you could do:
siteProducts
.Where(product => product.Category.ParentId == null)
.Min(product => product.Price)
.ToString();
I have a many-to-many relationship between tables of Games and Genres. During an analysis, i need to get items from Games that match specific criteria.
The problem is, to check for this criteria, i need to analyse genres of this specific game. And linq won't let me do it.
My request now looks like this:
var result = GDB.Games.Where((g)=>
g.GamesToGenres.Select((gtg)=>
(weights.ContainsKey(gtg.Genre.Name) ? weights[gtg.Genre.Name]:0.0)
).Sum() > Threshhold
).ToArray();
When I execute it, I receive SQL exception
Only one expression can be specified in the select list when the
subquery is not introduced with EXISTS.
Is there a workaround? How can i perform such Select inside of Where?
EDIT: weights is a Dictionary<string, double>.
EDIT: I was playing with lambdas, and found out a strange thing in their behaviour:
this code won't work, throwing nvarchar to float conversion exception:
Func<string, double> getW = (name) => 1;
var t = GDB.Games.Where((g)=>
g.GamesToGenres.Select((gtg)=>
getW(gtg.Genre.Name)
).Sum() > Threshhold
).ToArray();
but this one will work nicely:
var t = GDB.Games.Where((g)=>
g.GamesToGenres.Select((gtg)=>
1
).Sum() > Threshhold
).ToArray();
This leads me to conclusion that linq lambdas are not usual lambdas. What's wrong with them, then? What are their limitations? What i can and what i can't do inside of them? Why is it ok for me to place a .select call inside of lambda, but not my own call of getW?
RESOLVED. See the answer below. Long story short, C# can't into clojures unless explicitly told so. If anyone knows better answer, i am still confused.
Your problem is you're trying to select something form the dictionary weights that exists in your application and not in your DB. If it was the result of a query to your DB, use the query.Single(...) in its place
Well, i am confused beyond imagination. The following code works perfectly:
Func<Game, bool> predicate = (g) =>
g.GamesToGenres.Select((gtg) =>
(weights.ContainsKey(gtg.Genre.Name) ? weights[gtg.Genre.Name] : 0.0)
).Sum() > Threshhold;
var t = GDB.Games.Where(predicate).ToArray();
careful reader might want to say "Hey! Isn't that the very same code you wrote in the question? You just explicitly assigned it to a variable!", and he will be right. Right now it seems like C# lambda processor is a piece of something, and it creates clojure only when you explicitly declare a lambda. If someone can describe this phenomena to me, i will be gratefull, for right now i am more confused than a newborn baby.
LINQ allows you to combine SQL data with local data like (Dictionary, etc.) with one restriction. You need to select data from SQL first. This means your code will work if you replace GDB.Games.Where with GDB.Games.ToList().Where. You can ask about performance, but you able to select a slice of data like GameId, Genre Name, etc. Then filter out games. Then return end list of full game's info by game ID list.
I have a model where a Product can have multiple PriceDrops. I'm trying to generate a list of products with the most recent price drops.
Getting the most recent price drops with the products loaded is easy enough, and I thought it would be the best way to start:
dlo.LoadWith<PriceDrop>(pd => pd.Product);
db.LoadOptions = dlo;
return db.PriceDrops.OrderBy(d=>d.CreatedTime);
Works great for a list of recent price drops, but I want a list of products. If I append a ".Select(d=>d.Product)" I get a list of Products back - which is perfect - but they are no longer associated with the PriceDrops. That is, if I call .HasLoadedOrAssignedValues on the products, it returns false. If I try to interrogate the Price Drops, it tries to go back to the DB for them.
Is there a way around this, or do I have to craft a query starting with Products and not use the Select modifier? I was trying to avoid that, because in some cases I want a list of PriceDrops, and I wanted to re-use as much logic as possible (I left out the where clause and other filter code from the sample above, for clarity).
Thanks,
Tom
Try loading the Products, ordered by their latest PriceDrop:
dlo.LoadWith<Product>(p => p.PriceDrops);
db.LoadOptions = dlo;
return db.Products.OrderBy(d => d.PriceDrops.Max(pd => pd.CreatedTime));
I understand from your question that you're trying to avoid this, why?
I think what you need here is the the AssociateWith method, also on the DataLoadOptions class.
dlo.AssociateWith<Product>(p => p.PriceDrops.OrderBy(d=>d.CreatedTime))