我有一个与T1
有多对多关系的表T2
,加入表为T12
,我希望从T2
获取相关记录, Id
中记录的T1
,使用EF和LINQ,我这样做:
var listIds = oContext.T12.Where(x => x.T1Id == id).Select(x => x.T2Id).ToList();
//then
var theList = oContext.T2.In(x => x.Id, listIds).ToList();
In
的实施。
我不认为这是从m-t-m关系查询数据的最佳方式。
但真正的问题是来自T2
的记录不是出现在SQL中的顺序(应用程序中的顺序问题):
但他们的订单是T2Id:58478,58479,58480,58481
修改
我使用OrderBy
按顺序获取listIds
,但列表仍未按顺序排列,我访问了SSMS,并进行了查询:
SELECT* FROM T2 WHERE Id IN(58481, 58478, 58479, 58480)
这就是结果:
答案 0 :(得分:2)
你的直觉是正确的,这不是最好的方式。如果您正确地在Entity Framework中设置多对多关系,则不必提及联接表T12
。
调整到您的班级:
class T1
{
public int Id {get; set;}
// every T1 has zero or more T2
public virtual ICollection<T2> T2s {get; set;}
// other properties
public int A {get; set;}
public string B {get; set;}
}
class T2
{
public int Id {get; set;}
// every T2 has zero or more T1
public virtual ICollection<T1> T1s {get; set;}
// other properties
public int C {get; set;}
public string D {get; set;}
}
public MyDbContext : DbContext
{
public DbSet<T1> T1s {get; set;}
public DbSet<T2> T2s {get; set;}
}
就是这样!实体框架将认识到您正在建模T1和T2之间的多对多关系,并为您创建额外的数据库表。
在你的linq查询中,你不需要这个额外的表。当您访问集合时,Linq将创建连接。
“给我所有的T1,其中属性X == ......所有的T2属性Y == ......”
using (var myDbContext = new MyDbContext)
{
var result = myDbContext.T1s
.Where(t1 => t1.X == ...)
.Select(t1 = new
{
// select the T1 properties you want
A = t1.A,
B = t1.B,
// a T1 has zero or more T2s
// select the T2s you want:
T2s = t1.T2s
.Where(t2 => t2.Y == ....)
.Select(t2 => new
{ // Take the T2 properties you want
C = t2.C,
D = T2.D,
}),
});
}
你也可以从T2开始:
var result = myDbContext.T2s
.Where(t2 => t2.Y == ...)
.Select(t1 = new
{
// select the T1 properties you want
C = t2.C,
D = t2.C,
// a T2 has zero or more T1s
// select the T1s you want:
T1s = t2.T1s
.Where(t1 => t1.Y == ....)
.Select(t1 => new
{ // Take the T1 properties you want
A = t1.A,
B = T2.B,
}),
});
因为您访问多对多中的集合属性,所以Entity Framework知道必须执行与额外创建的多对多表的连接。
结果类似于GroupJoin。如果您想要它未分组,更像是真正的联接,您需要SelectMany
var result = MyDbContext.T1s.SelectMany(t1 => t1.T2s
.Select(t2 => new
{
A = t1.A,
B = t1.B,
C = t2.C,
D = t2.D,
});
根据我的经验,无论何时正确定义一对多和多对多关系,您都很少需要考虑加入。您只需访问属性,实体框架将自动知道要加入哪些表。