I have simple sql Left join query as:
select a.firstName+' '+a.lastName Name from account a left join
EH_PP_TeacherEvaluations b
on a.id=b.EH_PP_TE_TeacherAcctID
I wanted to do it in linq.
I tried to do it as follows:
List<Entity.TeacherEval> list = new List<Entity.TeacherEval>();
list = (from a in context.accounts join b in context.EH_PP_TeacherEvaluations on
a equals b.EH_PP_TE_TeacherAcctID into te
from b in te.DefaultIfEmpty()
select new { a.firstName+' '+a.lastName}
).ToList();
return list;
But its not working.
Error on 'join' :
Type interface failed in call to Group join.
and on row:
select new { a.firstName+' '+a.lastName}
Please help me.
Where i am making mistake, i am new with linq.
Edit 1 :
public class TeacherEval
{
public Guid ID { get; set; }
public DateTime? ProcessStartDate { get; set; }
public DateTime? ProcessEndDate { get; set; }
public Guid? AccountID { get; set; }
public Guid? StatusId { get; set; }
public TeacherEval() { }
public TeacherEval(DB.EH_PP_TeacherEvaluation item)
{
this.ID = item.EH_PP_TE_TeacherEvalID;
this.ProcessStartDate = item.EH_PP_TE_TeacherEvalProcessStartDate;
this.ProcessEndDate = item.EH_PP_TE_TeacherEvalProcessEndDate;
this.AccountID = item.EH_PP_TE_TeacherAcctID;
this.StatusId = item.EH_PP_TESRT_TeacherEvalStatusIDEH;
}
public DB.EH_PP_TeacherEvaluation ToDB()
{
var rec = new DB.EH_PP_TeacherEvaluation();
rec.EH_PP_TE_TeacherEvalProcessStartDate = this.ProcessStartDate;
rec.EH_PP_TE_TeacherEvalProcessEndDate = this.ProcessEndDate;
rec.EH_PP_TE_TeacherAcctID = this.AccountID;
rec.EH_PP_TESRT_TeacherEvalStatusIDEH = this.StatusId;
return rec;
}
public DB.EH_PP_TeacherEvaluation ToDB(DB.EH_PP_TeacherEvaluation rec)
{
rec.EH_PP_TE_TeacherEvalProcessStartDate = this.ProcessStartDate;
rec.EH_PP_TE_TeacherEvalProcessEndDate = this.ProcessEndDate;
rec.EH_PP_TE_TeacherAcctID = this.AccountID;
rec.EH_PP_TESRT_TeacherEvalStatusIDEH = this.StatusId;
return rec;
}
}
Try this:
var result= (
from a in context.accounts
from b in context.EH_PP_TeacherEvaluations
.Where(w=>w.EH_PP_TE_TeacherAcctID == a.id).DefaultIfEmpty()
select new {name= a.firstName+" "+a.lastName}
).ToList();
This will be translate to a LEFT JOIN
Edit
It looks to me like you want to fill a new object. Do I would suggest you doing something like this:
public class ResultDTO
{
public string Name { get; set; }
}
And then the query like this:
var result= (from a in context.accounts
join b in context.EH_PP_TeacherEvaluations on
a.id equals b.EH_PP_TE_TeacherAcctID
into te
from b in te.DefaultIfEmpty()
select new ResultDTO
{
Name= a.firstName+" "+a.lastName
}
).ToList();
This will result into a List<ResultDTO>
Edit 2
Alternative you can also do this. If you just want the string:
var result= (from a in context.accounts
join b in context.EH_PP_TeacherEvaluations on
a.id equals b.EH_PP_TE_TeacherAcctID
into te
from b in te.DefaultIfEmpty()
select a.firstName+" "+a.lastName
).ToList();
This will result into a List<string>
do like this:
List<Entity.TeacherEval> list = (from a in context.accounts
join b in context.EH_PP_TeacherEvaluations
on a.id equals b.EH_PP_TE_TeacherAcctID into te
from b in te.DefaultIfEmpty()
select new Entity.TeacherEval
{Name = a.firstName+" "+a.lastName}).
ToList<Entity.TeacherEval>();
Your class should have property of Name:
public class TeacherEval
{
public string Name {get;set;}
}
Try this:
List<Entity.TeacherEval> list = (from a in context.accounts join b in
context.EH_PP_TeacherEvaluations on
a.id equals b.EH_PP_TE_TeacherAcctID into te
from b in te.DefaultIfEmpty()
select new Entity.TeacherEval { Name = a.firstName+' '+a.lastName}
).ToList();
You need to add a Property called Name in the class Entity.TeacherEval
OR
you can simply call the list into a variable like this
var list = (from a in context.accounts join b in
context.EH_PP_TeacherEvaluations on
a.id equals b.EH_PP_TE_TeacherAcctID into te
from b in te.DefaultIfEmpty()
select new { Name = a.firstName+' '+a.lastName}
).ToList();
Related
I have this class from my entity Framework, i want to store this result of my linq query in list to display it in my web form, i get this error message:
Error 4 Cannot implicitly convert type
'System.Collections.Generic.List' to
'System.Collections.Generic.List' \App_Code\Models\PackageModel.cs
this is my code:
thanks for a helping.
public partial class Package
{
public int ID { get; set; }
public int SchoolID { get; set; }
public int SessionID { get; set; }
public int LessonsID { get; set; }
public virtual Lesson Lesson { get; set; }
public virtual School School { get; set; }
public virtual Session Session { get; set; }
}
public List<Package> GetAllItemPackage()
{
try
{
using (MusicSchoolEntities db = new MusicSchoolEntities())
{
List<Package> packages = (from x in db.Packages
join y in db.Schools on x.SchoolID equals y.ID
join z in db.Sessions on x.SessionID equals z.ID
join w in db.Lessons on x.LessonsID equals w.ID
join q in db.Courses on w.CourseID equals q.ID
select new { SchoolTitle = y.TitleEn ,
SessionName = z.NameEn,
CourseTitle = q.TitleEn,
LessonPeriod = w.PeriodEn,
LessonPrice = w.PriceEn,
LessonDesc = w.DescriptionEn,
LessonPaymtd = w.PayMtdEn}).ToList();
return packages;
}
}
catch (Exception)
{
return null;
}
}
You have 2 problems there.
First is that your code return an anonymous type but you are trying
to populate a List<Package> - That is why you get the exception.
Secondly, the data you are trying to populate isn't like the Package class that you have so if you want to return such a list from a function you should create a new type of class to have all those properties.
So:
List<YourClass> packages = (from x in db.Packages
join y in db.Schools on x.SchoolID equals y.ID
join z in db.Sessions on x.SessionID equals z.ID
join w in db.Lessons on x.LessonsID equals w.ID
join q in db.Courses on w.CourseID equals q.ID
select new YourClass
{
SchoolTitle = y.TitleEn ,
SessionName = z.NameEn,
CourseTitle = q.TitleEn,
LessonPeriod = w.PeriodEn,
LessonPrice = w.PriceEn,
LessonDesc = w.DescriptionEn,
LessonPaymtd = w.PayMtdEn
}).ToList();
return packages;
And of course GetAllItemPackage should return: List<YourClass> and not List<Package>
How can I use Left join in Linq that I write SQL query?
select
p.Name, p.Family,
E.EmployTypecode, E.employtypeName, E.EmplytyppeTye
from
personnel as p
left join
Employee as E on E.EmployTypecode = p.EmployTypecode
Use Join keyword instead of Left join and it is mandatory to use "INTO" keyword and "DefaultIfEmpty()" method as right table returns null value.
var query = from p in personnel
join e in Employee on p.EmployTypecode equals e.EmployTypecode into t
from nt in t.DefaultIfEmpty()
orderby p.Name
select new
{
p.Name, p.Family,
EmployTypecode=(int?)nt.EmployTypecode, // To handle null value if Employtypecode is specified as not null in Employee table.
nt.employtypeName, nt.EmplytyppeTye
}.ToList();
Do it like this :
var query =
from p in personnel
join e in Employee
on p.EmployTypecode equals e.EmployTypecode
into temp
from j in temp.DefaultIfEmpty()
select new
{
name = p.name,
family = p.family,
EmployTypecode = String.IsNullOrEmpty(j.EmployTypecode) ? "" : j.EmployTypecode,
......
}
var q=(
from pd in dataContext.personnel
join od in dataContext.Employee
on pd.EmployTypecode equals od.EmployTypecode
into t
from rt in t.DefaultIfEmpty()
orderby pd.EmployTypecode
select new
{
EmployTypecode=(int?)rt.EmployTypecode,
pd.Name,
pd.Family,
rt.EmplytyppeTye
}
).ToList();
Why dont use SQL query to convert EF to LIST.
In EF 6.1
write
public class personnel
{
public String Name { get; set; }
public String Family { get; set; }
public String EmployTypecode { get; set; }
public String employtypeName { get; set; }
public String EmplytyppeTye { get; set; }
}
List<personnel> personnels = dbentities.Database.SqlQuery<personnel>(#"select
p.Name, p.Family,
E.EmployTypecode, E.employtypeName, E.EmplytyppeTye
from
personnel as p
left join
Employee as E on E.EmployTypecode = p.EmployTypecode ").ToList();
I am using LINQ with Entity framework to joining three tables and I am returning IList interface.
I want to apply foreach loop on this returned value so I can populate values in my model.
This is how I am joining:
public IList GetData(long Id)
{
//var q = dataContext.tblUsers.AsEnumerable().Join(dataContext.tblUsersProfiles.AsEnumerable(),)
var query = from u in dataContext.tblUsers
join p in dataContext.tblUsersProfiles on u.ProfileId equals p.Id
join c in dataContext.tblComments on u.Id equals c.Commentedby
where c.Id == Id
select new { u.Firstname, u.Lastname, p.ProfilePicPath, c.Comment, c.CommentDate };
return query.ToList();
}
I want to populate these values in my List of Model. I have tried this:
var lst = repository.GetDate(Id);
foreach (var item in lst)
{
}
But I am unable to access item Firstname/Lastname etc.
I also tried using object item and object[] item but they both are not working too.
How can I apply a foreachonIList`?
It will work fine If I'm be able to return DataTable instead of IList in this case.
You are creating an anonymous type. Just define a class for the result of your query, then the return type of your function should be like this:
public IList<YourClassName> GetData(long Id)
{
}
Finally set class values:
select new YourClassName
{
Firstname = u.Firstname,
Lastname = u.Lastname,
ProfilePicPath = p.ProfilePicPath,
Comment = c.Comment,
CommentDate = c.CommentDate
};
You're returning an anonymous list of objects in the method. You can access the properties by using reflection but this is abit slow at runtime. Easiest to get type information is by defining a class and use that in the select statement.
public class Person
{
public string Firstname { get; set; }
public string Lastname { get; set; }
/* ... */
}
public IList<Person> GetData(long Id)
{
var query = from u in dataContext.tblUsers
join p in dataContext.tblUsersProfiles on u.ProfileId equals p.Id
join c in dataContext.tblComments on u.Id equals c.Commentedby
where c.Id == Id
select new Person { u.Firstname, u.Lastname /* ... */ };
return query.ToList();
}
You should return not just IList interface but parametrised interface with your type. Now you returtint anounymouse object.
So what i want to suggest. Create this class:
public class MyCustomContainer
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public string ProfilePicPath { get; set; }
public string Comment { get; set; }
public string CommentDate { get; set; }
}
And the change your method like this:
public IList<MyCustomContainer> GetData(long Id)
{
//var q = dataContext.tblUsers.AsEnumerable().Join(dataContext.tblUsersProfiles.AsEnumerable(),)
var query = from u in dataContext.tblUsers
join p in dataContext.tblUsersProfiles on u.ProfileId equals p.Id
join c in dataContext.tblComments on u.Id equals c.Commentedby
where c.Id == Id
select new MyCustomContainer
{
Firstname = u.Firstname,
Lastname = u.Lastname,
ProfilePicPath = p.ProfilePicPath,
Comment = c.Comment,
CommentDate = c.CommentDate
};
return query.ToList();
}
Now you returning not anonymouse object within List so you can get all properties you need
You are creating an anonymous type:
select new { u.Firstname, u.Lastname, p.ProfilePicPath, c.Comment, c.CommentDate };
If you want to pass this data to other methods etc. you need to create a real class.
public class DataClass
{
public string Firstname { get; set; }
public string LastName{ get; set; }
public string ProfilePicPath { get; set; }
public string Comment { get; set; }
public DateTime CommentDate { get; set; }
}
and use it:
public IList<DataClass> GetData(long Id)
{
var query = from u in dataContext.tblUsers
join p in dataContext.tblUsersProfiles on u.ProfileId equals p.Id
join c in dataContext.tblComments on u.Id equals c.Commentedby
where c.Id == Id
select new DataClass
{
Firstname = u.Firstname,
Lastname = u.Lastname,
ProfilePicPath = p.ProfilePicPath,
Comment = c.Comment,
CommentDate = c.CommentDate
};
return query.ToList();
}
You must change GetData return type. Please try this:
public List<tblUsers> GetData(long Id)
{
//var q = dataContext.tblUsers.AsEnumerable().Join(dataContext.tblUsersProfiles.AsEnumerable(),)
var query = from u in dataContext.tblUsers
join p in dataContext.tblUsersProfiles on u.ProfileId equals p.Id
join c in dataContext.tblComments on u.Id equals c.Commentedby
where c.Id == Id
select new tblUsers { u.Firstname, u.Lastname, p.ProfilePicPath, c.Comment, c.CommentDate };
return query.ToList();
}
You're using an anonymous type so you can't cast it to anything when looping through your list. You could try using dynamic instead of var which means you can call any property on it as long as it exists at runtime:
foreach (dynamic item in lst)
{
string firstName = item.FirstName;
}
or explicitly defining a class for the result item like the other answers are suggesting.
I have the following classes.
Course;
public class Course
{
//pk
public int Id{ get; set; }
public int SourceCourseId { get; set; }
public string Name { get; set; }
}
Registration
public class Registration
{
//primary key
public int Id { get; set; }
//...more fields
public int CourseId { get; set; }
}
I want to obtain a collection of annonymous objects with the two fields below for all Courses that are Distinct in the registrations table that are not in the Courses table.
var distinctCourses = (from registration in db.Registrations
join courses in db.Courses on registration.CourseId equals courses.SourceCourseId
where registration.CourseId != courses.SourceCourseId
select new
{
SourceCourseId = registration.CourseId,
Name = registration.CourseName,
}).Distinct().ToList();
For some reason the above is returning 0... Any suggestions?
try a left join:
var query = from r in registrations
join c in courses on r.CourseId equals c.id into newCourses
from nullCourse in newCourses.DefaultIfEmpty()
where nullCourse == null
select new { }
Edit - per comment from Alex :
Also, your where clause needs to change to
where nullCourse == null
Edit - changed join columns and added correct where clause.
Edit - group registrations on CourseID so they will be distinct
var distinctCourses =
(from registration in db.Registrations
group registration by registration.CourseId into grp
from reg in grp
join courses in db.Courses on reg.CourseId equals courses.SourceCourseId into newCourses
from nullCourse in newCourses.DefaultIfEmpty()
where nullCourse == null
select new
{
SourceCourseId = reg.CourseId,
Name = reg.CourseName,
}).ToList();
Try this
var result = Registrations.GroupJoin(Courses,r=>r.CourseId,c=>c.SourceCourseId,
(k,g) => new {k,g})
.Where(x=>x.g.Count()==0)
.Select(s=> new {id=s.k.CourseId,name=s.k.CourseName});
I am new to linq can any body please help me out to convert following query to linq.
SELECT A.Name,
Sum(C.MoneyIN) - Sum(C.MoneyOut) AS Balance
FROM Customers A
JOIN Banks B ON A.Id = B.id
JOIN BankTransactions C ON B.Id = C.BankID
GROUP BY A.Name
I tried to convert it into linq
var query = from c in db.Customers
join b in db.Banks on c.Id equals b.CustomerId
join bt in db.BankTransactions on b.Id equals bt.BankId
group c by c.Name into Cust
select new
{
Name = c.Name,
Balance = Cust.Sum(bt.MoneyIn) - Cust.Sum(bt.MoneyOut)
};
Can anybody please tell me where I am wrong ?
Thanks in advance.
Try that:
var query = from c in db.Customers
join b in db.Banks on c.Id equals b.CustomerId
join bt in db.BankTransactions on b.Id equals bt.BankId
group bt by c.Name into Cust
select new
{
Name = Cust.Name,
Balance = Cust.Sum(x => x.MoneyIn) - Cust.Sum(x => x.MoneyOut)
};
Seems problem was that in last select you used c.Name but should Cust.Name as you already performed grouping.
Update 1.
And also Cust.Sum(bt.MoneyIn) => Cust.Sum(x => x.MoneyIn).
Update 2.
Also you are grouping by wrong prop. If you want to apply sum to your BankTransactions you need to group by it like:
group bt by c.Name into Cust
So working example might look like:
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Bank
{
public int CustomerId { get; set; }
public int Id { get; set; }
}
public class BankTransaction
{
public int BankId { get; set; }
public int MoneyIn { get; set; }
public int MoneyOut { get; set; }
}
And query that compiles:
var customers = new List<Customer>();
var banks = new List<Bank>();
var bankTransactions = new List<BankTransaction>();
var result = from c in customers
join b in banks on c.Id equals b.CustomerId
join bt in bankTransactions on b.Id equals bt.BankId
group bt by c.Name into Cust
select new { Name = Cust.Key, Balance = Cust.Sum(x => x.MoneyIn) - Cust.Sum(x => x.MoneyIn) };
In Sum you need to use alias of the object. See Sum() here and if MoneyIn and MoneyOut is int you have to use this overload
Chnage this:
Balance = Cust.Sum(bt.MoneyIn) - Cust.Sum(bt.MoneyOut)
to this:
Balance = Cust.Sum(x=>x.bt.MoneyIn) - Cust.Sum(x=>x.bt.MoneyOut)
and the Name of Cust is the Key of grouping:
select new
{
Name = Cust.Key,
Balance = Cust.Sum(x => x.bt.MoneyIn) - Cust.Sum(x => x.bt.MoneyOut)
};
Complete query:
var query = from c in db.Customers
join b in db.Banks on c.Id equals b.CustomerId
join bt in db.BankTransactions on b.Id equals bt.BankId
group new { bt.MoneyIn,bt.MoneyOut} by c.Name into Cust
select new
{
Name = Cust.Key,
Balance = Cust.Sum(x=>x.MoneyIn) - Cust.Sum(x=>x.MoneyOut)
};