Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Wednesday, June 5, 2013 7:19 PM
hi all,
i'm having a slight problem that i cannot find a solution on google. I'm doing MVC and I am doing a join. Here's a snip of my code:
// class member model
public class Member
{
[Required]
public int MemberID { get; set; }
[Required]
public string MemberName{ get; set; }
[Required]
public int CompanyID { get; set; }
[NoMapped]
public string CompanyName { get; set; }
}
// class company model
public class Company
{
[Required]
public int CompanyID { get; set; }
[Required]
public string CompanyName{ get; set; }
}
Here's the index() function from my MemberController
public ViewResult Index()
{
var query = from m in db.Members
join c in db.Companies on m.CompanyID equals c.CompanyID
select new Member()
{
MemberID = m.MemberID,
MemberName = m.MemberName,
CompanyID = m.CompanyID,
CompanyName = c.CompanyName
}
return View(query.ToList());
}
Error: The entity or complex type 'ProjectName.Models.Member' cannot be constructed in LINQ to Entities query.
I see that the type is different: When i do this: db.Member.ToList() then I get System.Collections.List<Member>; but with the code above i get System.Linq.IQueryable<Member>; I think it has to return System.Collections.Generic.List<Member>.
I'm new to this linq stuff. Any help is appreciated. Thanks.
All replies (16)
Wednesday, June 5, 2013 7:40 PM
Try this:
public ViewResult Index()
{
var query = from m in db.Members
join c in db.Companies on m.CompanyID equals c.CompanyID
select new {m,c};
var list = new List<Member>();
foreach(var item in query)
{
list.Add(new Member()
{
MemberID=item.m.MemberID,
MemberName=item.m.MemberName,
CompanyID=item.m.CompanyID,
CompanyName=item.c.CompanyName
});
}
return View(list);
}
Wednesday, June 5, 2013 7:40 PM
I believe you can cast to Member in the ToList call:
return View(query.ToList<Member>());
Wednesday, June 5, 2013 7:54 PM
Wang, i had something similar to that before. but i don't like the idea of going through the foreach to do it.
Wednesday, June 5, 2013 8:06 PM
var query = from m in db.Members
from c in db.Companies
where m.CompanyID == c.CompanyID
select new Member()
{
MemberID = m.MemberID,
MemberName = m.MemberName,
CompanyID = m.CompanyID,
CompanyName = c.CompanyName
}
return View(query.ToList());
Wednesday, June 5, 2013 8:12 PM
And i thought that's the solution =)
AceCorban, that doesn't work. It gives me the same error
Wednesday, June 5, 2013 8:16 PM
EvilScott .. =) nope. same error.
question though,
if you do
from m in db.Members
from c in db.Companies
will it performs faster than the join?
Wednesday, June 5, 2013 8:59 PM
Wang, i had something similar to that before. but i don't like the idea of going through the foreach to do it.
Then you probably can pass a anonymous type to your view:
public ViewResult Index()
{
var query = from m in db.Members
join c in db.Companies on m.CompanyID equals c.CompanyID
select new {m.MemberID,m.MemberName,m.CompanyID,c.CompanyName};
return View(query.ToList());
}
In your view your model should be of type List<dynamic>.
Thursday, June 6, 2013 5:21 PM
using anonymous type doesn't work. i guess there's no other solution than using the for loop that Wang suggested. however, i think there has to be a better way =)
Thursday, June 6, 2013 7:12 PM
After doing some more research, the problem is that the Entity framework does not actually allow you to project onto mapped entities, because the context you are using will not be able to track or maintain data integrity. If you do wish to do it though, it appears you might be able to get around it by converting it to a list collection first then populating the entity type after the fact. Try this:
var query = (from m in db.Members
join c in db.Companies on m.CompanyID equals c.CompanyID
select m).ToList();
var results = from m in query
select new Member()
{
MemberID = m.MemberID,
MemberName = m.MemberName,
CompanyID = m.CompanyID,
CompanyName = c.CompanyName
};
return View(results.ToList());
Thursday, June 6, 2013 8:31 PM
Thanks EvilScott.
I have not plug your code in and give it a try, I think it would work; however, it seems like two select statements against the db. It's not wrong, but performance wise it's not fast (i think).
I'll give it a try later tonight. If there's no way, I think Wang's solution is less heavy on the db.
Thursday, June 6, 2013 8:38 PM
It's not two select statements against the database. The first query gets the data from the database itself and immediately uses .ToList() to dump it into an instance not bound to the datacontext it was pulled from. Then the second statement is reading from the already populated info and creating the members.
Sunday, June 9, 2013 6:45 PM
Evil, you're right about that and i think your solution is the best answer.
Wednesday, June 26, 2013 10:23 AM
EvilScott, today I get a chance to use the your suggested solution; however, in the second query the compiler complains that c does not exist in the current context.
Wednesday, June 26, 2013 11:18 AM
thats because the list only has the mebers data, no company data. create an anonymous object to hold both.
var query = (from m in db.Members
join c in db.Companies on m.CompanyID equals c.CompanyID
select new {m=m, c=c}).ToList();
var results = from q in query
select new Member()
{
MemberID = q.m.MemberID,
MemberName = q.m.MemberName,
CompanyID = q.m.CompanyID,
CompanyName = q.c.CompanyName
};
return View(results.ToList());
but this is much simpler looking as:
var results = (from m in db.Members
join c in db.Companies on m.CompanyID equals c.CompanyID
select new {m=m, c=c}).ToList().Select(
{
MemberID = q.m.MemberID,
MemberName = q.m.MemberName,
CompanyID = q.m.CompanyID,
CompanyName = q.c.CompanyName
});
return View(results.ToList());
Thursday, July 4, 2013 8:58 PM
When you need to return an IQueryable from a method the ToList() options does not exist (not matter what your opinion on using this way is).
The only way to evaluate dynamic projections appears to be enumeration - ie. the for(var item in query) approach.
For those looking for a more concise syntax you may prefer this:
IList<dynamic> results = Enumerable.Cast<object>(query).Cast<dynamic>().ToList();
Monday, September 16, 2013 2:52 AM
The only problem here were two braces.
public ViewResult Index()
{
var query = from m in db.Members
join c in db.Companies on m.CompanyID equals c.CompanyID
select new Member
{
MemberID = m.MemberID,
MemberName = m.MemberName,
CompanyID = m.CompanyID,
CompanyName = c.CompanyName
}
return View(query.ToList());
}
Please let me know whether it works?