Reputation: 3410
I am trying to retrieve records to populate a ListView, using Entity Framework, from three tables.
An example structure of these tables is:
luPersonType
PersonTypeID
PersonTypeDescription
People
PersonID
FirstName
LastName
{...}
PersonTypeID
EmployeeInfo
EmployeeInfoID
PersonnelNumber
StartDate
{...}
PersonID
luPersonType is a lookup table which holds two values ("Customer" and "Employee) used to differentiate types of people. luPersonType has a 1:M relationship to People.
If a person is an Employee, they will have additional details stored about them in the EmployeeInfo table. People has a 1:1 (theoretical) relationship to EmployeeInfo.
Example data:
luPersonType
PersonTypeID----PersonTypeDescription
1---------------Customer
2---------------Employee
People
PersonID----FirstName---LastName---PersonTypeID
1-----------Jane--------Doe--------1
2-----------John--------Doe--------2
3-----------Bob---------Smith------1
4-----------Sue---------Jones------2
EmployeeInfo
EmployeeInfoID----PersonnelNumber----StartDate----PersonID
1-----------------ABC123-------------1/1/13-------2
2-----------------XYZ456-------------2/1/13-------4
As you can see, both John and Sue are Employees and they each have a record in the EmployeeInfo table.
I would like to return a list of all people, with their PersonType description, and EmployeeInfo details (if any):
luPersonType.PersonTypeDescription,
People.LastName + ", " + People.FirstName AS FullName,
EmployeeInfo.PersonnelNumber,
EmployeeInfo.StartDate
This would result in:
PersonTypeDescription----FullName----PersonnelNumber----StartDate
Customer-----------------Doe, Jane---NULL---------------NULL
Employee-----------------Doe, John---ABC123-------------1/1/13
Customer-----------------Smith, Bob--NULL---------------NULL
Employee-----------------Jones, Sue--XYZ456-------------2/1/13
I first tried this code, but it only returned People that had records in both People and EmployeeInfo (inner join?):
using(MyEntities ctx = new MyEntities())
{
var query = from a in ctx.People
join b in ctx.luPersonType on a.PersonTypeID equals b.PersonTypeID
join c in ctx.EmployeeInfo on a.PersonID equals c.PersonID
orderby a.LastName
select new
{
b.PersonTypeDescription,
FullName = a.LastName + ", " + a.FirstName,
c.PersonnelNumber,
c.StartDate
};
RadListViewPeople.DataSource = query.ToList();
}
Since that seemed to result in an inner join, I looked into different ways to write this query. Here is my second try:
using (MyEntities ctx = new MyEntities())
{
var query = from a in ctx.People
orderby a.LastName
select new
{
a.luPersonType.PersonTypeDescription,
FullName = a.LastName + ", " + a.FirstName,
PersonnelNumber = from b in a.EmployeeInfos
select b.PersonnelInfo
StartDate = from b in a.EmployeeInfos
select b.StartDate
}
}
This returned all four records, but it returned the datatype for PersonnelNumber (System...String) and StartDate (System...DateTime).
I have read about the .Include method, but I haven't been able to get that to work, either.
The second query gave me all the records that I wanted and it seems cleaner to me, but I just can't figure out how to retrieve the actual data values from EmployeeInfo.
Any help will be greatly appreciated!
Upvotes: 2
Views: 3154
Reputation: 93424
If your model is setup properly, you should simply be able to do this (note: not tested, so i'm not 100% sure the syntax is correct, but it should give you what you need to solve the problem, i'm also guessing at the name of the navigation property EmployeeInfo):
var query = from a in ctx.People
let b = a.EmployeeInfo.FirstOrDefault()
orderby a.LastName
select new {
a.luPersonType.PersonTypeDescription,
FullName = a.LastName + ", " + a.FirstName,
b.PersonnelNumber,
b.StartDate
};
The problem here is the PersonnelInfo is actually 1:many, even though you only use it as a 1:1, so you have to select the first record or Default to return null if no association.
Note: this only works when using IQueryable, because EF does not treat null references as problems. If this were converted to an IEnumerable, then the code above would throw an execption on PersonnelNumber and StartDate because b would be null for some records.
Upvotes: 1