Help with QueryOver and WhereExists - c#

I have a problem. I have Persons and Cats. Each Person has some Cats (there is a foreign key in Cats that points to the primary key in Persons). Each Cat has an Age. I want to select the Persons that have "Old" Cats. I want ALL the Cats of these persons, and not only the "Old" Cats.
I need to do it with the QueryOver syntax.
In T-SQL it would be something like:
SELECT P.*, C.*
FROM Persons P
LEFT JOIN Cats C
ON P.Id = C.OwnerId
WHERE EXISTS (
SELECT 1
FROM Cats C2
WHERE P.Id = C2.OwnerId AND C2.Age > 5)
I know I have to use the subqueries, and I could to easily with the "old" nhibernate syntax (the Criteria/DetachedCriteria), but I can't do it in QueryOver syntax.
I DON'T want an "IN" condition. My Primary Key is a complex key, so I can't do it with the IN.
var persons = session.QueryOver<Person>.WithSubquery.WhereExists( ??? );

Example taken from this page and adapted (tested with my own classes):
The trick seems to be using an alias.
Person personAlias = null;
IList<Person> persons =
session.QueryOver<Person>(() => personAlias).WithSubquery
.WhereExists(QueryOver.Of<Cat>()
.Where(c => c.Age > 5)
.And(c => c.Owner.Id == personAlias.Id)
.Select(c => c.Owner))
.List<Person>();

Related

C# : How to get anonymous type from LINQ result

I need to get NewsImage field and list of categories Ids that associated with the news in Many to Many relationship ... but it gives me error:
The type of one of the expressions in the join clause is incorrect.Type inference failed in the call to 'Join'.
My code looks like this
var Result1 = (from c in db.News
join d in db.Categories
on c.NewsId equals d.News.Select(l => l.NewsId)
where c.NewsId == 1
select new { c.NewsImagePath, d.CategoryId }).ToList();
Assuming you have a navigation property defining the n-n relation I would write:
var result = db.News
.Where(x => x.NewsId == 1)
.SelectMany(x => x.Categories,
(news, category) => new { news.NewsImagePath, category.CategoryId })
.ToList();
The problem is inside the on statement.
on c.NewsId equals d.News.Select( l => l.NewsId )
The Select on the right-hand side will return a IEnumerable of news, which is not what you want.
Something like this would technically work:
on c.NewsId equals d.News.Select( l => l.NewsId ).FirstOrDefault()
But it does not make sense logically.
I suspect the whole query should be built differently. I think you want to join when the category list of news contains the news item. In that case, you can't use the join statement, it would look somewhat like this:
from n in db.News
from c in db.Categories
where c.News.Select( ne => ne.NewsId ).Contains( n.NewsId )
select new { n.NewsImagePath, c.CategoryId }

Select from a table with Entity Framework

I have 3 tables:
Person
Groups
PersonsGroups
I need to select all persons when they are in the group from a list
(list from few groups)
I tried to select like this:
var tdd = GS.PersonsGroups.Include("Person")
.Where(r => s.Contains(r.GroupID.Value))
.Select(c => c.Person);
But it is not Person is it PersonGroup and I don't have all Person prop
What is the right way to get it?
Thank you very much in advance
If I understand correct, you are seeking for something like this
List<int> groupIds = ...;
var query = db.Persons
.Where(p => p.PersonGroups.Any(pg => groupIds.Contains(pg.GroupID.Value));

Changing a linq query to filter on many-many

I have the following Linq query
public static List<string> selectedLocations = new List<string>();
// I then populate selectedLocations with a number of difference strings, each
// corresponding to a valid Location
viewModel.people = (from c in db.People
select c)
.OrderBy(x => x.Name)
.ToList();
// Here I'm basically filtering my dataset to include Locations from
// my array of selectedLocations
viewModel.people = from c in viewModel.people
where (
from a in selectedLocations
where a == c.Location.Name
select a
).Any()
select c;
This works really well as each Person record can have a single Location.
My question is how do I change this query if a Person can have a one-many relationship with Location? So a Person can have 2 Locations as an example, what do I need to change this line to?
where a == c.Location.Name
Thanks!
you can try to replace this part :
where a == c.Location.Name
with this :
where c.Locations.Any(o => o.Name == a)
that will return true if any Location in Locations property has Name equals a.

How to retrieve data from table "a" based on different values in table "b"

var c = from p in db.Testings
where p.id == Convert.ToInt32(k)
select new{p.ItemId};`
The above Linq is returning multiple amount of rows containing different ItemIds.
Now, I am trying to retrieve all the rows from Questions table containing all those ItemIds I got returned in the above linq. As expected, the below code is not working. Can anyone please help me with this logic or correct my code if it's a minor logical mistake.
var cfk = from p in db.Questions
where p.ItemId == Convert.ToInt32(c)
select p;
GridView4.DataSource = cfk;
GridView4.DataBind();
Something like:
var cfk = from p in db.Questions
where c.Contains(p.ItemId)
select p;
You can perform an inner join using LINQ.
http://msdn.microsoft.com/en-us/library/bb397941.aspx
I would probably do the join on the Db side during your Get() if possible, though.
Based on your choice of 'cfk' as the second variable name I'm guessing you have setup your database such that Questions.ItemId is a foreign key into Testings, where Testings.ItemId is the primary key of Testings and Testings.id is some other non-key column.
If that is the case you can say:
var cfk = db.Testings
.Where(t => t.id == k)
.SelectMany(t => t.Questions);
or
var cfk = db.Questions
.Where(t => t.Testing.id == k);
If there is no foreign key relationship you would need to do a Join as others suggest e.g.
var cfk = db.Testings
.Where(t => t.id == k)
.Join(db.Questions, t => t.ItemId, q => q.ItemId, (t, q) => q);

EF 6 select from other table without navigation property

I have a small problem which I need a help to solve:
I have following situation:
For example: I want to select all students who have a dog.
I have 2 tables:
students
id name petid
pet
id name
BUT there is no specified foreign key between them no navigation property, although I have but I haven't specified it and I don't want for my case, but I still want to make a correct select statement.
So with navigation property i could query like this:
var students = (student s in context.students where s.Pet.Name.Equals("dog").ToList();
I would avoid doing this also
var students = context.students
foreach(student s in students)
{
string pet = (from pet p in context.pets where p.Id==s.PetId select p.name).SingleOrDefault();
if(pet=="dog")
{
//do something
}
}
Of course it would be easy to make navigation property, but for my case I really don't want to.
So my question is how can i do this kind of query simple and with only one to DB?
Use a join.
var students = (from s in context.students
join p in context.pets on s.petid equals p.id
where p.name == "dog"
select s).ToList();
For the lambda syntax, you can use this:
var students = context.students.Join(context.pets.Where(p => p.name== "dog"), //filter the pets
student => student.PetId, //left side key for the join
pet => pet.id, //right side key for the join
(student, pet) => student); //what do you want to select

Categories