How to do Inner join on multiple columns in Nhibernate Query Over - nhibernate

I want to do a query over for one of my entity but I want to get done for multiple columns.
Questions (Table)
Id Name OpenId CloseId
1 A 1 NULL
2 B 2 3
3 C 4 5
4 D 6 7
5 E 8 9
Now the GroupTable is
Id Name
1 AA
2 BB
3 CC
4 DD
5 EE
6 FF
7 GG
8 HH
9 II
Now I want to do a queryOver on Question table with both OpenId and CloseId which are from the group table. How can I do.
I can achieve easily from the SQL query like.
select * from questions q
inner join GroupTable g on q.OpenId = g.Id Or q.CloseId = g.Id
How can I get this through Queryover ?
The class structure looks like this :
public class Question
{
public int Id { get; set; }
public GroupTable OpenTable { get; set; }
public GroupTable CloseTable { get; set; }
}
public class GroupTable
{
public int Id { get; set; }
public int Name { get; set; }
}

can you try it.
GroupTable openTable = null;
GroupTable closeTable = null;
Question ques = null;
List<Question> quesList = new List<Question>();
quesList = session.QueryOver<Question>(() => ques)
.JoinAlias(() => ques.CloseTable, () => closeTable)
.JoinAlias(() => ques.OpenTable, () => openTable)
.Where(() => ques.CloseTable == closeTable && ques.OpenTable == openTable)
.List().ToList();

Related

Linq query for joining many to many tables

I'm new at LINQ and need your advice.
I have 2 tables like these:
public class Subjects
{
public Subjects()
{
Classes = new List<Classes>();
}
public int Id { get; set; }
public string SubjectName { get; set; }
public virtual List<Classes> Classes { get; set; }
}
public class Classes
{
public Classes()
{
Subjects = new List<Subjects>();
}
public int Id { get; set; }
public string ClassName { get; set; }
public virtual List<Subjects> Subjects { get; set; }
}
And Entity Framework create SubjectClasses
public SubjectsMap()
{
this.HasKey(s => s.Id);
this.Property(s => s.SubjectName)
.IsRequired()
.HasMaxLength(50);
this.ToTable("Subjects");
this.HasMany(c => c.Classes)
.WithMany(s => s.Subjects)
.Map(cs =>
{
cs.MapLeftKey("SubjectId");
cs.MapRightKey("ClassId");
cs.ToTable("SubjectClasses");
});
}
Subject---- SubjectClasses ----- Classes
My Context doesn't have SubjectClasses, so I need to convert the SQL query to Linq or Lambda. But Linqpad doesn't help me or I can't use it. I simply want to take Firstname, SubjectName
SELECT st.Firstname, s.SubjectName
FROM SubjectClasses sc
INNER JOIN Subjects s on s.Id = sc.SubjectId
INNER JOIN Students st on st.ClassId = sc.ClassId
WHERE sc.ClassId = 3
It's working.
(from st in context.Students
from s in context.Subjects
join c in context.Classes
on new { stuId = st.ClassId } equals new { stuId = c.Id }
select new ComplexExamResult
{
Id = c.Id,
Firstname = st.Firstname,
SubjectName = s.SubjectName
}).Where(c => c.Id == classId).AsNoTracking().ToList();

How can I do an outer join with a group by in SQLite?

I have three tables in SQLite that were created from these classes. I joined these with the SQL below.
public class Phrase {
[PrimaryKey, NotNull]
public string PhraseId { get; set; }
public int PhraseNum { get; set; }
public int CategoryId { get; set; }
}
public class Category {
[PrimaryKey, NotNull]
public int Id { get; set; }
public int GroupId { get; set; }
public string Name { get; set; }
public bool Selected { get; set; }
}
public class CategoryGroup {
[PrimaryKey, NotNull]
public int Id { get; set; }
public string Name { get; set; }
public bool IsToggled { get; set; }
}
So far I have this SQL
SELECT CG.NAME, COUNT(*) AS TotalPhraseCount
FROM Phrase AS P
JOIN Category AS C ON P.CategoryId = C.Id
JOIN CategoryGroup AS CG ON C.GroupId = CG.Id
WHERE C.Selected = 1
GROUP BY C.GroupId
Which gives me as one of the Categories in Category group has 11 phrases and it's Selected:
CategoryGroupName PhrasesCount
A 20
However what I need is to see every CategoryGroup row and a 0 if there are no Categories selected in that group. So for example this which includes the CategoryGroup B which has no Categories selected:
CategoryGroupName PhrasesCount
A 20
B 0
C 0
I think I can do this with an outer join but I am not sure how to implement that in SQL.
Each category contains many phrases
Each category group contains many categories
Each category belongs to just one Category group
Each phrase belongs to just one Category
Hope that helps
Here's the output I have from Juan's query. Not sure why there is a 1 in rows B and C
CategoryGroupName PhrasesCount
A 20
B 1
C 1
SELECT CG.NAME, COUNT(C.GroupId) AS TotalPhraseCount
FROM CategoryGroup AS CG
LEFT JOIN Category AS C
ON CG.Id = C.GroupId
AND C.Selected = 1
LEFT JOIN Phrase AS P
ON P.CategoryId = C.Id
GROUP BY CG.NAME
Use left join
SELECT CG.NAME, COUNT(*) AS TotalPhraseCount
FROM Phrase AS P
left JOIN Category AS C ON P.CategoryId = C.Id
and C.Selected = 1
left JOIN CategoryGroup AS CG ON C.GroupId = CG.Id
GROUP BY C.GroupId

Issue with querying database using LINQ query to bring list of DTO

I have a LINQ query in the below format. The problem is that I am passing a list of 100 consumerID in the form of list. I want to query the database and bring result for
all these 100 consumerIds. However the query brings back the result only for the first guy. I am suspecting I am missing something in the where clause. I am sure there are matching results in the database for all these 100 consumerIds.
public ICollection<ConsumerExchangeChangeDto> GetByConsumers(List<int> consumerIDs)
{
EnrollmentReportingModel db = (EnrollmentReportingModel)Context.DbContext;
var results = (from ecew in db.A
join ecewe in db.B on ecew.ID
equals ecewe.ExchangeChangeEnrollmentWindowID into temp
from j in temp.DefaultIfEmpty()
join cecr in db.C on ecew.ConsumerExchangeChangeRequestID equals cecr.ID
join con in db.D on cecr.ConsumerID equals con.ID
where consumerIDs.Contains(con.ID) && !ecew.Deleted
select new E
{
ConsumerID = con.ID,
OrganizationID = con.OrganizationID,
StartDate = ecew.StartDate,
EndDate = ecew.EndDate,
Deleted = ecew.Deleted
}).ToList();
return results;
}
Here is the dto class
public class E : ILzDto
{
public int ConsumerID { get; set; }
public int OrganizationID { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public bool Deleted { get; set; }
}
I think you want Any, not contains:
public ICollection<ConsumerExchangeChangeDto> GetByConsumers(List<int> consumerIDs)
{
EnrollmentReportingModel db = (EnrollmentReportingModel)Context.DbContext;
var results = (from ecew in db.A
join ecewe in db.B on ecew.ID
equals ecewe.ExchangeChangeEnrollmentWindowID into temp
from j in temp.DefaultIfEmpty()
join cecr in db.C on ecew.ConsumerExchangeChangeRequestID equals cecr.ID
where consumerIDs.Any(x => x == cecr.ConsumerID) && !ecew.Deleted
select new E
{
ConsumerID = cecr.ConsumerID,
OrganizationID = con.OrganizationID,
StartDate = ecew.StartDate,
EndDate = ecew.EndDate,
Deleted = false
}).ToList();
return results;
}

Join one Table to the Same Table for MULTIPLE Times in Lambda

I have a Student entity and a City entity in my MVC4 application and there are 3 City codes in Student table like that:
Student Entity:
StudentID | StudentName | BirthCity | LivingCity | UniversityCity |
1 Christof 01 02 03
...
City Entity:
CityID | CityName |
01 NewYork
02 Los Angeles
03 Washington
...
I want to join Student entity to City entity and show 3 different City names according to their values as indicated above. I have tried with some examples, but they are related to joining different tables (I need to aggregate the same table 3 times : City). How can I do this?
I think it's not a good idea to use join. See below:
Model:
public class Student
{
public Student()
{
StudentID = 0;
StudentName = string.Empty;
BirthCity = string.Empty;
LivingCity = string.Empty;
UniversityCity = string.Empty;
}
public Student(int id ,string name, string bName,string lName,string uName)
{
StudentID = id;
StudentName = name;
BirthCity = bName;
LivingCity = lName;
UniversityCity = uName;
}
public int StudentID { get; set; }
public string StudentName { get; set; }
public string BirthCity { get; set; }
public string LivingCity { get; set; }
public string UniversityCity { get; set; }
}
query:
Students.Select (
s => new Student()
{
StudentID = s.StudentID,
StudentName = s.StudentName,
BirthCity = Cities
.Where (c => (c.CityID == s.BirthCity))
.Select (c => c.CityName)
.SingleOrDefault (),
LivingCity = Cities
.Where (c => (c.CityID == s.LivingCity))
.Select (c => c.CityName)
.SingleOrDefault (),
UniversityCity = Cities
.Where (c => (c.CityID == s.UniversityCity))
.Select (c => c.CityName)
.SingleOrDefault ()
}
)
You could do this with subqueries. It could also be done with joins.
SELECT StudentId,
(SELECT CityName FROM City WHERE CityId = s.BirthCity),
(SELECT CityName FROM City WHERE CityId = s.LivingCity),
(SELECT CityName FROM City WHERE CityId = s.UniversityCity)
FROM Student s

How does fetch work [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
NHibernate Join Fetch(Kind)
I have read article.
http://fabiomaulo.blogspot.com/2010/03/conform-mapping-components.html
Tried to reproduce it on my project and got strange behavioral.
I have two entites:
Plan
{
public virtual int Id { get; set; }
public virtual Payer Payer { get; set; }
}
Payer
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
Mapping for it:
orm.Cascade<Payer, Plan >(CascadeOn.Persist | CascadeOn.Merge);
orm.Cascade<Plan, Payer>(CascadeOn.None);
Fetch:
mapper.Customize<CarePlan>(cm => cm.ManyToOne(o => o.Payer, x =>
x.Fetch(FetchKind.Join)));
Simple get:
var plan = session.Query<Plan>().Where(c=>c.Id ==
1).SingleOrDefault();
Console.WriteLine(plan.Payer.Name);
And I got this queries:
select careplan0_.Id
careplan0_.PayerId
from CarePlans careplan0_
where careplan0_.Id = 1 /* #p0 */
and other query
SELECT payer0_.Id ,
payer0_.Name as Name
FROM Payers payer0_
WHERE payer0_.Id = 2
Why I got 2 queries? How can I get one query with join?
Try
var plan = session.Query()
.Where(c=>c.Id == 1)
.Fetch(x => x.Player).Eager
.SingleOrDefault();
Try disabling lazy load, so it will eager load by default