foreach on IEnumerable or IList - c#

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.

Related

SQL TO Linq, How to return an object and fill properties

i have a question, i want to create a linq query that returns a list of object.
This is the model
public class Test
{
[Key]
public int ID { get; set; }
[Required]
[StringLength(5)]
public string Code { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[NotMapped]
public string Reference { get; set; }
}
The query that i want to do is simple: context.Test.ToList();
this returns the database mapping Reference is null since is not part of the table.
Now if i create a linq query i know that i can do select new { all fields here }
i want to avoid this:
select new Test
{
Reference = r,
ID = t.ID,
Code = t.Code,
Name = t.Name
}).ToList();
is it possible to do something like this
(from t in context.Test
join r in context.Reference on f.ID equals r.ID
select new
{
t.Reference = r.Reference,
t
}).ToList();
i want to set the Reference value inside the same query, is that possible?
What are you asking is not directly supported in LINQ to Entities - neither projection to entity type, nor expression block which is the only way to assign properties of an existing object.
As usual, the typical workaround is to split the query on two parts - one being LINQ to Entities query selecting the necessary data (usually into intermediate anonymous type), then switch to LINQ to Objects with AsEnumerable() and do the rest - in this case using block inside Select:
var result =
(from t in context.Test
join r in context.Reference on f.ID equals r.ID
select new { t, r.Reference }
).AsEnumerable()
.Select(x =>
{
x.t.Reference = x.Reference;
return x.t;
}).ToList();
Don't select an anonymous object, just create a new T from the one you have.
(from t in context.Test
join r in context.Reference on t.ID equals r.ID
select new Test
{
Reference = r,
ID = t.ID,
Code = t.Code,
Name = t.Name
}).ToList();
EDIT:
To avoid having to manually copy over all the properties
public class Test
{
public int ID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Reference { get; set; }
public Test CopyWithReference(string reference)
{
var copy = (Test)this.MemberwiseClone();
copy.Reference = reference;
return copy;
}
}
Then...
(from t in context.Test
join r in context.Reference on t.ID equals r.ID
select t.CopyWithReference(r)).ToList();
Try following :
(from t in context.Test
join r in context.Reference on f.ID equals r.ID
select new Test()
{
ID = t.ID,
Code = t.Code,
Name = t.Name,
Reference = r.Reference
}).ToList();
Try:
var result = context.Test.Include("Reference").ToList();
or:
var result = context.Test.Include(t => t.Reference).ToList();
or Try Lambda Expressions:
var result = context.Test.Select(t => new {
t,
t.Reference = t.Reference.Select(r => new {
r.Reference })
}).AsEnumerable().Select(x => x.r).ToList();

A type that implements IEnumerable 'System.Collections.Generic.List`1' cannot be initialized in a LINQ to Entities query

I am trying to create object of some class inside the Linq query but gives me an error as set title of the question.
My query is:
List<oneViewModel> workOrderInfoList = (from abc in db.ABC
join customer in db.Customers on abc.CustomerId equals customer.CustomerId into customers
select new oneViewModel()
{
CustomerId = abc.CustomerId,
OrderNumber = workOrderInfo.OrderNumber,
OrderDate = abc.OrderDate,
SecondClassList = new List<SecondClass>(),
}).ToList();
I have define the list of class in as object inside oneViewModel.
public class ABC
{
public DateTime? WorkOrderDate { get; set; }
public long CustomerId { get; set; }
public string CustomerName { get; set; }
public List<SecondClass> SecondClassList { get; set; }
}
Initialise the secondClass List inside your ViewModel constructor:
Public oneViewModel()
{
SecondClassList = new List<SecondClass>();
)
Remember to remove the initialisation from the Linq query.
Edit
List<oneViewModel> workOrderInfoList = (from abc in db.ABC
join customer in db.Customers on abc.CustomerId equals customer.CustomerId into customers
select new oneViewModel()
{
CustomerId = abc.CustomerId,
OrderNumber = workOrderInfo.OrderNumber,
OrderDate = abc.OrderDate,
SecondClassList = abc.SecondClassList
}).ToList();
Edit 2
Your oneViewModel should look something like this:
public class oneViewModel
{
public oneViewModel
{
SecondClassList = new List<SecondClass>();
}
Public List<SecondClass> SecondClassList { get; set; }
}
The linq query should look like this:
List<oneViewModel> workOrderInfoList = (from abc in db.ABC
join customer in db.Customers on abc.CustomerId equals customer.CustomerId into customers
select new oneViewModel()
{
CustomerId = abc.CustomerId,
OrderNumber = workOrderInfo.OrderNumber,
OrderDate = abc.OrderDate
}).ToList();
Now that you will have a list of oneViewModel objects.
You need to execute query first and then initialize list, e.g.:
List<oneViewModel> workOrderInfoList = (from abc in db.ABC
join customer in db.Customers on abc.CustomerId equals customer.CustomerId into customers).ToList()
Select(n => new oneViewModel()
{
CustomerId = n.CustomerId,
OrderNumber = workOrderInfo.OrderNumber,
OrderDate = n.OrderDate,
SecondClassList = new List<SecondClass>(),
}).ToList();

Linq - Join where ID's !=, select new + distinct?

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

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

Convert simple t-sql query to linq

I'm struggleing with a query. I know how to write it in SQL, but after looking at many examples and useing Linqer, I haven't had any success converting this to linq. Could someone point me in the right direction...
SELECT contacts.firstname, contacts.lastname
FROM businesscontacts INNER JOIN
contacts ON businesscontacts.contactsid = contacts.contactsid INNER JOIN
contactscontactcodes ON contacts.contactsid = contactscontactcodes.contactsid
This is, I believe, very close, but contacts is of course not defined...
string sendto = from businesscontacts in db.businesscontacts
from t in contacts.contactcodes
select new {
businesscontacts.contacts.firstname,
businesscontacts.contacts.lastname
};
If I prepend the db context...
string sendto = from businesscontacts in db.businesscontacts
from t in db.contacts.contactcodes
select new {
businesscontacts.contacts.firstname,
businesscontacts.contacts.lastname
};
Then contact codes is not available
You need to use the Linq join keyword to join the tables, just like you would in sql.
Here is a great resource to get you on your way with Line. 101 LINQ Samples
var results = from bc in db.businesscontacts
join c in db.contacts
on bc.contactsid equals c.contactsid
join cc in db.contacts.contactcodes
on c.contactsid = cc.contactsid
select new { FirstName = c.FirstName, LastName = c.LastName;
If you have foreign key constraints set up on your database you don't need to do any joins at all. Note that I changed the declaration of sendto since string doesn't make sense here.
var sendto = from businesscontact in db.businesscontacts.Include(bc => bc.contact)
select new {
businesscontact.contact.firstname,
businesscontact.contact.lastname
};
Try:
var names = from bContacts in db.businesscontacts
join contacts in db.contacts on bContacts.contactsid equals ontacts.contactsid
join cCodes in db.contacts.contactcodes on contacts.contactsid equals cCodes.contactsid
select new
{
FirstName = contacts.firstname,
LastName = contacts.lastname
};
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var businesscontacts = new List<businesscontacts>();
var contacts = new List<contacts>();
var contactcodes = new List<contactcodes>();
var sendto = from bc in businesscontacts
from c in contacts
from cc in contactcodes
where bc.Contactid == c.Contactid && cc.Contactid == c.Contactid
select new
{
c.FirstName,
c.LastName
};
}
}
class businesscontacts
{
public int Contactid { get; set; }
}
class contacts
{
public int Contactid { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
class contactcodes
{
public int Contactid { get; set; }
}
}

Categories