Jam*_*zer 11 linq-to-entities c#-4.0 entity-framework-4.1
我有Table1与以下关系(他们没有强制执行,他们只创建导航属性的关系)
Table1 (*)->(1) Table2 Table1 (*)->(1) Table3 Table1 (*)->(1) Table4 Table1 (*)->(1) Table5
使用急切的加载代码看起来像
IQueryable<Table1> query = context.Table1s;
query = query.Include(Table1 => Table1.Table2);
query = query.Include(Table1 => Table1.Table3);
query = query.Include(Table1 => Table1.Table4);
query = query.Include(Table1 => Table1.Table5);
query = query.Where(row => row.Table1Id == table1Id);
query.Single();
Run Code Online (Sandbox Code Playgroud)
我尝试组织Include()语句的每一种方式,包含的第一个表在其生成的TSQL中都有一个Inner Join,剩下的就是Left Outer Join(我希望所有这些都是Left Outer).我不是实体分裂,它们只是FK的普通表.
如果DefaultIfEmpty()是唯一的解决方案,有人可以解释除了包含的第一个表之外的所有表都提供预期的SQL的原因吗?
我的理解是导航属性的默认行为是LEFT OUTER但我无法获得所有属性来生成默认值.
任何帮助将非常感激.
先感谢您!
-----创建TSQL(为简洁而修改但结构相同)-------
(@p__linq__0 int)SELECT [Limit1].[Table1Id] AS [Table1Id], [Limit1].[OtherData] AS [OtherData] FROM ( SELECT TOP (2) [Extent1].[Table1Id] AS [Table1Id], [Extent1].[OtherData] As [OtherData] FROM [dbo].[Table1] AS [Extent1] INNER JOIN [dbo].[Table2] AS [Extent2] ON [Extent1].[Table2Id] = [Extent2].[Table2Id] LEFT OUTER JOIN [dbo].[Table3] AS [Extent3] ON [Extent1].[Table3Id] = [Extent3].[Table3Id] LEFT OUTER JOIN [dbo].[Table4] AS [Extent4] ON [Extent1].[Table4Id] = [Extent4].[Table4Id] LEFT OUTER JOIN [dbo].[Table5] AS [Extent5] ON [Extent1].[Table5Id] = [Extent5].[Table5Id] WHERE [Extent1].[Table1Id] = @p__linq__0 ) AS [Limit1]
Sla*_*uma 20
EF似乎INNER JOIN
用于包括必需和LEFT OUTER JOIN
包含可选的导航属性.例:
public class Order
{
public int Id { get; set; }
public string Details { get; set; }
public Customer Customer { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果我在... 上定义Customer
为必需属性Order
public class MyContext : DbContext
{
public DbSet<Order> Orders { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>()
.HasRequired(o => o.Customer)
.WithMany();
}
}
Run Code Online (Sandbox Code Playgroud)
...并发出此查询...
using (var ctx = new MyContext())
{
var result = ctx.Orders
.Include(o => o.Customer)
.Where(o => o.Details == "Peanuts")
.FirstOrDefault();
}
Run Code Online (Sandbox Code Playgroud)
...我得到这个SQL:
SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[Details] AS [Details],
[Extent2].[Id] AS [Id1],
[Extent2].[Name] AS [Name]
FROM [dbo].[Orders] AS [Extent1]
INNER JOIN [dbo].[Customers] AS [Extent2]
ON [Extent1].[Customer_Id] = [Extent2].[Id]
WHERE N'Peanuts' = [Extent1].[Details]
Run Code Online (Sandbox Code Playgroud)
如果我将模型配置更改.HasRequired(o => o.Customer)
为...
.HasOptional(o => o.Customer)
Run Code Online (Sandbox Code Playgroud)
...我得到完全相同的查询,除了INNER JOIN [dbo].[Customers] AS [Extent2]
被替换为:
LEFT OUTER JOIN [dbo].[Customers] AS [Extent2]
Run Code Online (Sandbox Code Playgroud)
从模型的角度来看,它是有道理的,因为你说如果你根据需要定义关系,就永远不会Order
没有a .如果您通过删除数据库中的强制执行来规避此要求,并且如果您实际上没有客户的订单则违反了您自己的模型定义.Customer
如果您遇到这种情况,只有解决方案可能会使关系成为可选关系.我不认为可以控制使用时创建的SQL Include
.
在 EF 中,IQueryable.Include()
如果没有导航属性基于强制关系,则 EF 将使用第一个表。它期望在模式中至少强制执行一个关系,并且应该使用第一个关系进行编码IQueryable.Include()
,然后使用以下命令添加其他表Include()