我認爲那些連接沒有被正確鏈接。
在第二次連接中,第二個參數引用了外部集合。這將是第一次加入new { User = user, SchemeName = schemeName })
的預計匿名類型。
假設有對用戶類的屬性LifeAssurance,然後我猜你想要做的第二加入基於從用戶對象屬性,像這樣:
var trs = db.Users
.Join(db.SchemeNames,
user => user.Pension.PensionSchemeNameID,
schemeName => schemeName.SchemeNameID,
(user, schemeName) => new { User = user,
SchemeName = schemeName })
.Join(db.SchemeNames,
x => x.User.LifeAssurance.LifeAssuranceSchemeNameID,
schemeName => schemeName.SchemeNameID,
(x, schemeName) => new { User = x.User,
PensionSchemeName = x.SchemeName,
LifeAssuranceSchemeName = schemeName })
.Where(a => UserIDs.Contains(a.User.UserName))
.Select(a => new TRSViewModel{
UserName = a.User.UserName,
FirstName = a.User.UserDetails.FirstName,
LastName = a.User.UserDetails.LastName,
Salary = a.User.UserDetails.Salary,
PensionSchemeName = a.PensionSchemeName.Name,
LifeAssuranceSchemeName = a.LifeAssuranceSchemeName.Name
});
這可以寫上查詢語法(可能更易於閱讀):
var trs = from user in db.Users
join pensionSchema in db.SchemeNames
on user.Pension.PensionSchemeNameID equals pensionSchema.SchemeNameID
join lifeAssuranceSchema in db.SchemeNames
on user.LifeAssurance.LifeAssuranceSchemeNameID equals lifeAssuranceSchema.SchemeNameID
where UserIds.Contains(user.UserName)
select new TRSViewModel{
UserName = user.UserName,
FirstName = user.UserDetails.FirstName,
LastName = user.UserDetails.LastName,
Salary = user.UserDetails.Salary,
PensionSchemeName = pensionSchema.Name,
LifeAssuranceSchemeName = lifeAssuranceSchema.Name }
最後,考慮到這些都是內部連接,因此任何用戶沒有退休金或人壽保險架構將不予退還。如果你想左連接,你可以不喜歡的方式描述here(雖然我猜你不需要這個否則像user.Pension.PensionSchemeNameID
表達式將拋出一個NullReferenceException如果有用戶沒有退休金)
var query =
from user in db.Users
from pensionScheme in db.SchemeNames
.Where(s => s.SchemeNameID == user.Pension.PensionSchemeNameID)
.DefaultIfEmpty()
from lifeAssuranceScheme in db.SchemeNames
.Where(s => s.SchemeNameID == user.LifeAssurance.LifeAssuranceSchemeNameID)
.DefaultIfEmpty()
select new { User = user,
Pension = pensionScheme,
LifeAssurance = lifeAssuranceScheme}
我也很快測試在內存中的集合使用下面的代碼與查詢,但他們應該通過實體框架被正確地轉換爲SQL:
public class SchemeName
{
public int SchemeNameID { get; set; }
public string Name { get; set; }
}
public class Pension
{
public int PensionSchemeNameID { get; set; }
}
public class LifeAssurance
{
public int LifeAssuranceSchemeNameID { get; set; }
}
public class User
{
public string Name { get; set; }
public Pension Pension { get; set; }
public LifeAssurance LifeAssurance { get; set; }
}
public static class db
{
public static IEnumerable<User> Users = new List<User>() {
new User { Name = "User 1",
Pension = new Pension { PensionSchemeNameID = 1 },
LifeAssurance = new LifeAssurance { LifeAssuranceSchemeNameID = 2 } },
new User { Name = "User 2",
Pension = new Pension { PensionSchemeNameID = 1 },
LifeAssurance = new LifeAssurance { LifeAssuranceSchemeNameID = 2 } },
new User { Name = "User 3",
Pension = new Pension { PensionSchemeNameID = 1 },
LifeAssurance = new LifeAssurance { LifeAssuranceSchemeNameID = -999 }},
new User { Name = "User 4",
Pension = new Pension { PensionSchemeNameID = -999 },
LifeAssurance = new LifeAssurance { LifeAssuranceSchemeNameID = 2 } }
};
public static IEnumerable<SchemeName> SchemeNames = new List<SchemeName>() {
new SchemeName{ SchemeNameID = 1, Name = "Scheme 1" },
new SchemeName{ SchemeNameID = 2, Name = "Scheme 2" }
};
}
private void Run()
{
var innerJoinQuery1 = db.Users
.Join(db.SchemeNames,
user => user.Pension.PensionSchemeNameID,
schemeName => schemeName.SchemeNameID,
(user, schemeName) => new
{
User = user,
SchemeName = schemeName
})
.Join(db.SchemeNames,
x => x.User.LifeAssurance.LifeAssuranceSchemeNameID,
schemeName => schemeName.SchemeNameID,
(x, schemeName) => new
{
User = x.User,
PensionSchemeName = x.SchemeName,
LifeAssuranceSchemeName = schemeName
})
.Where(a => a.User.Name.StartsWith("User "))
.Select(a => new
{
UserName = a.User.Name,
PensionSchemeName = a.PensionSchemeName.Name,
LifeAssuranceSchemeName = a.LifeAssuranceSchemeName.Name
});
var innerJoinQuery2 = from user in db.Users
join pensionSchema in db.SchemeNames
on user.Pension.PensionSchemeNameID equals pensionSchema.SchemeNameID
join lifeAssuranceSchema in db.SchemeNames
on user.LifeAssurance.LifeAssuranceSchemeNameID equals lifeAssuranceSchema.SchemeNameID
where user.Name.StartsWith("User ")
select new
{
UserName = user.Name,
PensionSchemeName = pensionSchema.Name,
LifeAssuranceSchemeName = lifeAssuranceSchema.Name
};
var lefJoinQuery =
from user in db.Users
from pensionScheme in db.SchemeNames
.Where(s => s.SchemeNameID == user.Pension.PensionSchemeNameID)
.DefaultIfEmpty()
from lifeAssuranceScheme in db.SchemeNames
.Where(s => s.SchemeNameID == user.LifeAssurance.LifeAssuranceSchemeNameID)
.DefaultIfEmpty()
select new
{
UserName = user.Name,
PensionSchemeName = pensionScheme != null ? pensionScheme.Name : "No Pension",
LifeAssuranceSchemeName = lifeAssuranceScheme != null ? lifeAssuranceScheme.Name : "No Life Assurance"
};
foreach (var result in innerJoinQuery1)
Print(result.UserName, result.PensionSchemeName, result.LifeAssuranceSchemeName);
Console.WriteLine();
foreach (var result in innerJoinQuery2)
Print(result.UserName, result.PensionSchemeName, result.LifeAssuranceSchemeName);
Console.WriteLine();
foreach (var result in lefJoinQuery)
Print(result.UserName, result.PensionSchemeName, result.LifeAssuranceSchemeName);
Console.WriteLine();
Console.ReadKey();
}
private void Print(string user, string pension, string lifeAssurance)
{
Console.WriteLine(String.Format("User: '{0}', Pension: '{1}', Life Assurance: '{2}'", user, pension, lifeAssurance));
}
}
將會產生預期的輸出:
對於第一內連接查詢
用戶: '用戶1',退休金: '方案1',人壽保險: '方案2'
用戶: '用戶2',年金:'方案1' ,人壽保險: '方案2'
對於第二內連接查詢
用戶: '用戶1',退休金: '方案1',人壽保險: '方案2'
用戶: '用戶2',養老金: '方案1',人壽保險: '計劃2'
左連接查詢
用戶: '用戶1',養老金: '方案1',人壽保險: '方案2'
用戶: '用戶2',養老金: '方案1',人壽保險: '方案2'
用戶: '用戶3',養老金:'計劃1',人生保證:'沒有生命保證」
用戶: '用戶4',養老: '沒有退休金',人壽保險: '計劃2'
都在同一個表中的'PensionSchemeName'和'LifeAssuranceSchemeName'值? –