Here is what my model looks like:
I'm trying to get the count of distinct Assesors by a certain EventId.
Here's the code I'm trying to use:
var x = db.Assessors.Select(a => (a.Assessments.Select(y => y.EventFacility.EventId == 138))).Count();
Unfortunately, I must be coding this wrong because instead of getting the expected result (a count of 9, in this case) I'm getting the wrong result: 35.
I'm wondering if someone can take a look at my LINQ statement and tell me what I'm doing wrong?
You need to use Where and Any like this:
var result = db.Assessors
.Where(a => a.Assessments.Any(y => y.EventFacility.EventId == 138));
What this is saying is that you want all Assessors that are parents of any Assessment that is related to that particular Event.
You're going about this backward, start from what you know (the event since you have it's ID) and navigate to what you want through the navigation properties.
It's impossible to tell from your schema as it includes neither the properties nor the mapping type 1:1? 1:N? Can't know from simple lines
It would probably look Something like this
var x = db.Events
.Where(ev=>ev.Id == 138)
.SelectMany(ev=>ev.EventFacilities) //(i'm assumine possibly multiple and not 1 per event, once again schema doesn't show it, if it's not the case change SelectMany to Select)
.SelectMany(ef=>ef.Assesments) // Same assumption as above
.Select(as=>as.Assessor) // Asuming otherwise here, if wrong change Select to SelectMany
.Distinct(); // Ignore duplicate assessors
Note that your question is impossible to answer as is, this is a best effort but if you want help you should give "all" the information required, not strip out what doesn't immediately seem relevant, it would've been much easier if you took an actual screenshot of your entity diagram instead of what you made up.
Related
First of all, sorry for my bad english.
I have a little trobule figurering this one out.
I have three tables and I need to make it so that the user can decide witch columns to fetch from the database.
I have tried using Dynamic nuget, but wont work.
The code i need is something like the line below.
var res = session.QueryOver<MyObject>().Select(x => x.decidedByUser).List();
Is this even possible or do I need to make some kind of workaround? Maybe something like getting all the values and then select? :-)
var columnProjection = Projections.Property(() => aliasForTable.Column1)
you can use above variable in nhibernate select statement to decide which column you want to fetch. Create this assignment for each of your case and you're done
I'm having a strange issue trying to order a list based on whether or not it contains a particular string value. Within a view, I have a list on my viewmodel for which I would like to display those objects which are not "snoozed" first and then ordered by whether or not their title contains the word "order". So my code is as follows:
var sortedFaults = accountFaultContainer.Faults.Values.OrderBy(f => f.IsSnoozed).ThenByDescending(f => f.Title.ToLower().Contains("order"));
I then loop through this list and add the 'faults' to my table using a foreach loop...
foreach (Fault fault in sortedFaults)
This works in some cases but not in others. I've been trying to single out those that do not behave as expected but there is no clear difference. For example, in once case, a title of "Full failing sync" was ordered both before and after "Failing order syncs". But it is not the case that this always misbehaves; in some tables the ordering is working.
Has anybody come across a similar issue before? Or is there something blatantly obvious I'm missing? I'm scratching my head here!
You order by IsSnoozed first, so that takes priority.
.OrderBy(f => f.IsSnoozed)
.ThenByDescending(f => f.Title.ToLower().Contains("order"));
Try it the other way around:
.OrderBy(f => f.Title.ToLower().Contains("order"))
.ThenByDescending(f => f.IsSnoozed);
I have a query with a lot of includes, and I'm wondering if I can do Takes on some of the includes.
For example, here's one of my queries, with the (illegal) Take illustrating what I want to do.
var primaryLocation = context.Locations
.Include("PhoneNumbers")
.Include("Invoices").Take(50)
.Include("Invoices.Items")
.Include("Schedules")
.Include("Staffs")
.SingleOrDefault(d => d.Id == locationId);
Currently the only way I can think to do it would be like so:
var primaryLocation = context.Locations
.Include("Invoices")
.Include("Etc")
.SingleOrDefault(d => d.Id == locationId);
primaryLocation.Invoices = primaryLocation.Invoices.Take(50).ToList();
I'd prefer not doing it that way, since means pulling back the entire Invoice list from the database, which I don't need.
Is there a handy way to build the Take into my query?
Seems like have two conflicting criteria for what you're doing. I'm guessing here, but you didn't leave us all that much to go on.
Since your primaryLocation.Invoices = primaryLocation.Invoices.Take(50).ToList(); statement only makes use of 1 of your includes, I'm assuming you're doing more things with your primaryLocation than what you've shown us. This leads me to believe that you want that primaryLocation to include all of the stuff. And then you seem not to want more than those 50, so that's not all of the stuff after all then... To me this is a contradiction. If you require all, you should include it all.
If you want your 50 invoices selection specifically you could get those separately in its own query. I use NHibernate myself, so I'm not sure of the syntax for future's in Entity framework, but if you want to ask for multiple things with only 1 round-trip to the server, in NHibernate you can make a series of queries into futures to allow this. I expect Entity framework has something similar.
In short, what I'm suggesting is that if you want primaryLocation to include all of your data, then that's what you'll get, and if you're after more specific information with filters like Take, then you might want to query more specifically.
Use projection instead of blindly calling Include if you don't want everything:
var primaryLocation = context.Locations
.Select(location => new {
Id = location.Id,
Name = location.Name,
// ... other properties needed on the front end
RecentInvoices = location.Invoices
// really should sort if you're only taking 50
.OrderByDescending(invoice => invoice.CreatedAt)
.Take(50),
AllPhoneNumbers = location.PhoneNumbers,
})
.SingleOrDefault(location => location.Id == locationId);
You could use projection to get just the invoice information you need too, I just didn't want to over-complicate the example.
Using this method you get exactly the data you want without adding confusion. It also allows you to name your properties (such as RecentInvoices above) to add more meaning.
I've got a LINQ query that's returning no results when I know that it should be returning at least one. I'm building up the query dynamically. I looked at the result set in the debugger right before I get to the line that filters out all of the results and it contains hundreds of rows. After this line, it contains 0 when it really should contain at least one.
query = query.Where(x =>
x.Lineages.FirstOrDefault().Sire.Contains(options.PedigreeContains));
'x' in this case represents an entity called 'Horse'. 'options.PedigreeContains' is just a string value. The Lineages table looks like this:
ID HorseID Sire Dam etc...
I can even pull up a Horse entity in the debugger (the one I know should be returned as a result), inspect the Lineages property and see it fully populated, including the Sire value that matches my search. So everything SEEMS like it should be working, except there's obviously some issue with the LINQ query that I'm using.
Does anyone see anything inherently wrong with what I'm doing that would cause this to filter out results that I know should be there?
EDIT: For clarification, it's a 1-to-1 relationship. I know the Lineages object exists, I know there's only one, and I know it matches. It's just for some reason it's returning zero results so I thought there might be a problem with the way I wrote the query. If that query should work the way it's written though (minus all of the extra "possibilities" if no lineages exist, more than one, etc) then it must be an issue somewhere else in my code.
What if FirstOrDefault returns the "Default"? You'll get a NullReferenceException.
You are providing no means to order the Lineages, if the first one returned does not have the desired Sire containing option.PedigreeContains. In such a case, the result set would be empty, regardless of the other Sire's in the Lineages.
Actually answring your question: No. There is nothing inherently wrong with your query. It must be an issue somewhere else in your query construction, in the database structure or in your data.
When debugging, instead of enumerating and verifying the result count, copy the query expression value and look what the generated SQL looks like. You can do that before and after altering the IQueryable query. Other suggestions like #Jalalx use of .Any() to avoid what #John Saunders points out.
If you do FirstOrDefault() where you have it, aren't you taking the first of what could be many sires, so if a later one matches your where you won't find it?
query = query.Where(x =>
x.Lineages.FirstOrDefault(lineage => lineage.Sire.Contains(options.PedigreeContains))).Sire;
I'm fairly new to Linq and struggling using dynamic where over a many to many relationship.
Database tables are like so:
Products <-> Products_SubCategories <-> SubCategories
with Products_SubCategories being a link table.
My full linq statement is
db.Products.Where("it.SubCategories.SubCategoryID = 2")
.Include("SubCategories")
.OrderBy(searchOrderBy)
.Skip(currentPage * pageSize)
.Take(pageSize)
.ToList()
.ForEach(p => AddResultItem(items, p));
So ignoring everything bar the Where() I'm just trying to pull out all products which are linked to sub category ID 2, this fails with
To extract properties out of collections, you must use a sub-query to iterate over the collection., near multipart identifier, line 8, column 1.
I think using the SQL-esque syntax I can do a subquery as per this link. However I'm not sure how to do that in the lambda / chaining syntax.
This is the start of a search function and I would like to build up the where string dynamically, as I have with the searchOrderBy string to avoid a large SELECT CASE. Products is linked to another table via a link table that I will need to include once I understand how to do this example.
Any help would be much appreciated!
Thanks
This is wrong:
db.Products.Where("it.SubCategories.SubCategoryID = 2")
SubCategories is a list. It does not have a property called SubCategoryID. Rather, it contains a group of entities which each have a property called SubCategoryID. That's a critical distinction.
When you run into a situation where you don't know how to proceed in there are multiple problems, it is good to break the problem down into several, smaller problems.
Let's start by removing the dynamic query. It will be easier to solve the problem with a non-dynamic query. Once you've done that, you can go back and make it dynamic again.
So start by using the non-dynamic syntax. Type something like this in Visual Studio, and see what IntelliSense does for you:
db.Products.Where(p => p.SubCategories.
You will quickly see that there is no SubCategoryID property. Instead, you will see a bunch of LINQ API methods for working with lists. If you know LINQ well, you will recognize that the Any() method is what you want here:
db.Products.Where(p => p.SubCategories.Any(sc => sc.SubCategoryID == 2))
Go ahead and run that query. Does it work? If so, you can move ahead to making it dynamic. I'm no ESQL expert, but I'd start with something along the lines of:
db.Products.Where("EXISTS(SELECT SC FROM it.SubCategories AS SC WHERE SC.SubCategoryID = 2");
As an aside, I use MS Dynamic Query ("Dynamic LINQ") for this sort of thing rather than Query Builder, as it's more testable.
It worked for me.
db.Products.Where("SubCategories.Any(SubCategoryID = 2)")