Error getting when trying assign linq data into DTO class - c#

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 ....

Related

How to get sublist from left outter join table using linq query?

I have Users, Roles, and a UserRoles table. I'm trying to get a list of users with a sublist of all the roles they belong to.
I have the following query that's giving me issues when I try and populate a sublist. I am getting an Object reference not set to an instance of an object error when I attempt to use the rolesGroup IEnumerable. I've tried doing null checks but that throws another error saying Null TypeMapping in Sql Tree.
Any idea how I should be populating the Roles sublist?
Thanks!
var q = from u in _dbContext.Users
join ur in _dbContext.UserRoles on u.Id equals ur.UserId
join r in _dbContext.Roles on ur.RoleId equals r.Id into rolesGroup
from rg in rolesGroup.DefaultIfEmpty()
select new UserJS
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
Roles = rolesGroup.Select(x => x .Name).ToList(), //<--- FAILING HERE
};
//DTO
public class UserJS
{
public string Id { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<string> Roles { get; set; }
}
Write your query like this:
var q = from u in _dbContext.Users
join ur in _dbContext.UserRoles on u.Id equals ur.UserId
select new UserJS
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
Roles = _dbContext.Roles.Where(x=>x.Id == ur.RoleId).ToListAsync(),
};
I was able to get it to work using a sub query inside select.
var q = from u in _dbContext.Users.Include(x => x.Doctor)
select new UserJS
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
Roles = (from ur in _dbContext.UserRoles
join r in _dbContext.Roles on ur.RoleId equals r.Id
where ur.UserId == u.Id
orderby r.Name
select r.Name).ToList(),
};

How can I use Left join in linq that we use in sql?

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();

foreach on IEnumerable or IList

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.

Convert Sql Query To linq using sum with group by

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)
};

Left join on linq query giving error

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();

Categories