Asp.net mvc 查询中的多个联接
早些时候,我在向查询添加联接方面得到了一些帮助。我现在意识到我实际上需要在同一个查询中添加多个连接,但我尝试了许多方法(基于原始连接),但不断出现错误 我有一个叫做SchemeName的模型-Asp.net mvc 查询中的多个联接,asp.net-mvc,entity-framework,Asp.net Mvc,Entity Framework,早些时候,我在向查询添加联接方面得到了一些帮助。我现在意识到我实际上需要在同一个查询中添加多个连接,但我尝试了许多方法(基于原始连接),但不断出现错误 我有一个叫做SchemeName的模型- namespace TRS.Models { public class SchemeName { [Key] public int SchemeNameID { get; set; } [Display(Name = "Scheme Name
namespace TRS.Models
{
public class SchemeName
{
[Key]
public int SchemeNameID { get; set; }
[Display(Name = "Scheme Name")]
public string Name { get; set; }
public virtual ICollection<Benefit> Benefits { get; set; }
}
}
在我的控制器中,我有以下内容:
var trs = db.Users
.Join(db.SchemeNames,
user => user.Pension.PensionSchemeNameID,
schemeName => schemeName.SchemeNameID,
(user, schemeName) => new { User = user, SchemeName = 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.SchemeName.Name,
这对于显示PensionSchemeName非常有用,但我也需要显示LifeAssuranceSchemeName(以及其他),但正如我提到的,不断出现错误。我想我只需要添加一个附加的连接,包含LifeAssuranceSchemeName的详细信息,所以我尝试添加-
var trs = db.Users
.Join(db.SchemeNames,
user => user.Pension.PensionSchemeNameID,
schemeName => schemeName.SchemeNameID,
(user, schemeName) => new { User = user, SchemeName = schemeName })
.Join(db.SchemeNames,
la => la.Pension.PensionSchemeNameID,
schemeName => schemeName.SchemeNameID,
(user, schemeName) => new { User = user, SchemeName = schemeName })
.Where(a => UserIDs.Contains(a.User.UserName))
.Select(a => new TRSViewModel
但这给了我一个错误-
错误10“AnonymousType#1”不包含“Pension”的定义,并且找不到接受“AnonymousType#1”类型的第一个参数的扩展方法“Pension”(是否缺少using指令或程序集引用?)
知道如何添加这些附加联接吗?我认为这些联接没有正确链接 在第二个联接中,第二个参数引用外部集合。这将是从第一个join
new{User=User,SchemeName=SchemeName})
中投影的匿名类型
假设User类上有一个属性生命保证,那么我猜您希望基于User对象中的该属性进行第二次连接,如下所示:
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
});
这可以写在查询语法上(可能更容易阅读):
最后,考虑到这些是内部连接,因此任何没有养老金或人寿保险方案的用户都不会被返回。如果您想要左联接,可以执行类似于所描述的方法的操作(尽管我想您不需要这样做,否则user.Pension.PensionSchemeNameID
之类的表达式将在有没有Pension的用户时抛出NullReferenceException)
我已经使用内存集合中的以下代码快速测试了这些查询,但它们应该正确地转换为实体框架的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));
}
}
公共类SchemeName
{
公共int SchemeNameID{get;set;}
公共字符串名称{get;set;}
}
公营养老金
{
public int pensionschemenaid{get;set;}
}
公共舱人寿保险
{
公共int-LifeAssuranceSchemeNameID{get;set;}
}
公共类用户
{
公共字符串名称{get;set;}
公共养老金{get;set;}
公共人寿保险人寿保险{get;set;}
}
公共静态类数据库
{
public static IEnumerable Users=新列表(){
新用户{Name=“用户1”,
养老金=新养老金{PensionSchemeNameID=1},
人寿保险=新人寿保险{LifeAssuranceSchemeNameID=2},
新用户{Name=“用户2”,
养老金=新养老金{PensionSchemeNameID=1},
人寿保险=新人寿保险{LifeAssuranceSchemeNameID=2},
新用户{Name=“User 3”,
养老金=新养老金{PensionSchemeNameID=1},
人寿保险=新人寿保险{LifeAssuranceSchemeNameID=-999},
新用户{Name=“User 4”,
养老金=新养老金{PensionSchemeNameID=-999},
人寿保险=新人寿保险{LifeAssuranceSchemeNameID=2}
};
公共静态IEnumerable SchemeNames=new List(){
新SchemeName{SchemeNameID=1,Name=“Scheme 1”},
新SchemeName{SchemeNameID=2,Name=“Scheme 2”}
};
}
私家车
{
var innerJoinQuery1=db.Users
.Join(db.SchemeNames,
user=>user.Pension.PensionSchemeNameID,
schemeName=>schemeName.SchemeNameID,
(用户,schemeName)=>新建
{
用户=用户,
SchemeName=SchemeName
})
.Join(db.SchemeNames,
x=>x.User.LifeAssurance.LifeAssuranceSchemeNameID,
schemeName=>schemeName.SchemeNameID,
(x,schemeName)=>新建
{
User=x.User,
PensionSchemeName=x.SchemeName,
LifeAssuranceSchemeName=schemeName
})
.Where(a=>a.User.Name.StartsWith(“用户”))
.选择(a=>新建
{
用户名=a.User.Name,
PensionSchemeName=a.PensionSchemeName.Name,
LifeAssuranceSchemeName=a.LifeAssuranceSchemeName.Name
});
var innerJoinQuery2=来自db.Users中的用户
在db.SchemeNames中加入pensionSchema
在user.Pension.PensionSchemeNameID上等于pensionSchema.SchemeNameID
在db.SchemeNames中加入lifeAssuranceSchema
在user.LifeAssurance.LifeAssuranceSchemeNameID上等于lifeAssuranceSchema.SchemeNameID
其中user.Name.StartsWith(“用户”)
选择新的
{
用户名=user.Name,
PensionSchemeName=pensionSchema.Name,
LifeAssuranceSchemeName=lifeAssuranceSchema.Name
};
var-lefJoinQuery=
来自db.Users中的用户
来自db.SchemeNames中的pensionScheme
.Where(s=>s.SchemeNameID==user.Pension.PensionSchemeNameID)
.DefaultIfEmpty()
来自db.SchemeNames中的lifeAssuranceScheme
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 }
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}
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));
}
}