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)
};
Related
I need to assign Linq data into my DTO class, but this Linq query getting mt this error.
LINQ to Entities does not recognize the method 'System.String ToString(System.String, System.IFormatProvider)' method, and this method cannot be translated into a store expression.
I removed int convertion to avoid the error, then I got this error
the type of one of the expressions in join clause is incorrect. type inference failed in the call to join
My code as follows,
public class TextDto
{
public string AddedData { get; set; }
public string AddedTime { get; set; }
public string Sender { get; set; }
public string Name { get; set; }
public string Messsage { get; set; }
}
linq code,
var allText = from nm in context.NotificationMessages
join u in context.Users on new {
Sender = (int) nm.Sender
}
equals new {
Sender = u.UserId
}
select new {
nm.Id,
nm.AddedTime,
nm.Lobby.Branch.BranchName,
u.FirstName,
u.LastName,
nm.Message
};
var allTextList = allText.Select(data = >new TextOnDemandDto {
AddedTime = data.AddedTime.ToString("hh:mm tt", CultureInfo.InvariantCulture),
Messsage = data.Message,
Name = data.FirstName + " " + data.LastName
}).ToList();
This sql, which I converted into linq
SELECT nm.id,
nm.addedtime,
b.branchname,
u.firstname,
u.lastname,
nm.message
FROM notificationmessage nm
INNER JOIN lobby l
ON l.lobbyid = nm.fklobbyid
INNER JOIN branch b
ON b.branchid = l.fkbranchid
INNER JOIN [user] u
ON nm.sender = u.userid
Try to change your query to this:
var allText = (from nm in context.NotificationMessages
join u in context.Users
on nm.Sender equals u.UserId into ug
from u in ug.DefaultIfEmpty()
join l in context.Lobbys
on nm.fklobbyid eguals l.lobbyid into lg
from l in lg.DefaultIfEmpty()
join b in context.Branches
on l.fkbranchid equals b.branchid into bg
from b in bg.DefaultIfEmpty()
select new {
nm.Id,
nm.AddedTime,
b.BranchName,
u.FirstName,
u.LastName,
nm.Message
}).ToList();
Update:
To get records with FKNotificationMessageTypeId = 3 insert where clause between "from b.." and "select":
... from b ...
where nm.FKNotificationMessageTypeId == 3
select new ....
In the following LINQ Query I need to display All the customers with total number of their orders placed including the customers that have not placed any orders:
Models:
Public class Customer
{
public int CustomerId { get; set; }
public string Name{ get; set; }
}
Public class Order
{
public int OrderId { get; set; }
public int CustomerId { get; set; }
}
LINQ Query: Question: How can I display ALL customers (including the one that have no order) and total number of orders per customer (zero for those whose customerID is not in Orders table)
var Query1 = from c in Customers
join o in Orders into co
from t in co.DefaultIfEmpty()
select new {CustomerID = c.CustomerId, OrderID = (t == null ? 0 : t.OrderId)};
You basically need to do a LEFT JOIN between your Customer table and Customer Order table and then do a group by on that result to count the orders for each customer.
Assuming you have a class like this
public class CustomerOrder
{
public int CustomerId { set; get; }
public int? OrderId { set; get; }
}
This class is to store each item for the left join result
Now, you need to first do a LEFT JOIN and project the result of that to a list of CustomerOrder class objects, Then do a GroupBy on top of that
var usersWithCount = (from c in db.Customers
join o in db.Orders on c.CustomerId equals o.CustomerId
into result
from sub in result.DefaultIfEmpty()
select new CustomerOrder{ OrderId= sub!=null ? sub.OrderId :(int?) null,
CustomerId = u.CustomerId }
) // Here we have the left join result.
.GroupBy(g => g.CustomerId , (k, orders) => new {
CustomerId = k,
OrderCount = orders.Count(t=>t.OrderId !=null)}).ToList();
The result stored in usersWithCount will be a collection of annonymous object with a CustomerId and OrderCount property.
This isn't very efficient since it iterates through Orders for every customer, but it'll get the job done:
var query = Customers
.Select(c => new
{
Name = c.Name,
NumOrders = Orders.Count(o => o.CustomerId = c.CustomerId)
});
foreach (var result in query)
Console.WriteLine("{0} -> {1}", result.Name, result.NumOrders);
var Query1 = from c in Customers
join o in Orders on c.CustomerId equals o.CustomerId into OrdersGroup
from item in OrdersGroup.DefaultIfEmpty(new Order { OrderId = 0, CustomerId = 0 })
select new {CustomerID = c.CustomerId, OrderID = (item == null ? 0 : item.OrderId)};
this will return all customers (even if they have no orders ) and orders
https://dotnetfiddle.net/BoHx2d
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 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 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();