C# 实体框架-can';不要让左外连接工作

C# 实体框架-can';不要让左外连接工作,c#,.net,entity-framework,entity-framework-4.1,C#,.net,Entity Framework,Entity Framework 4.1,请参阅下面2个版本的代码及其生成的SQL。我希望加载首选项,但我也希望只带来我的用户首选项,因此我使用WHERE子句。但一旦我把它放进去,我就再也不会有外部连接了。为什么? var query = from p in context.Preferences join up in context.UserPreferences on p.PreferenceKey equals up.PreferenceKey into outer

请参阅下面2个版本的代码及其生成的SQL。我希望加载首选项,但我也希望只带来我的用户首选项,因此我使用WHERE子句。但一旦我把它放进去,我就再也不会有外部连接了。为什么?

var query = from p in context.Preferences
                            join up in context.UserPreferences on p.PreferenceKey equals up.PreferenceKey into outer
                            from up in outer.DefaultIfEmpty()
                            select new MobileRESTEntities.UserPreference
                            {
                                CreatedOn = (up == null) ? p.CreatedOn : up.CreatedOn,
                                UpdatedOn = (up == null) ? p.CreatedOn : (up.UpdatedOn ?? up.CreatedOn),
                                PreferenceId = p.PreferenceId,
                                Value = (up == null) ? p.ValueDefault : up.Value,
                            };
其中:

var query = from p in context.Preferences
                            join up in context.UserPreferences on p.PreferenceKey equals up.PreferenceKey into outer
                            from up in outer.DefaultIfEmpty()
                            where up.UserKey.Equals((int)user.ProviderUserKey)
                            &&
                            (
                            (up == null)
                            ||
                            ((up.UpdatedOn > lastSyncOn && up.UpdatedOn != null) || (up.CreatedOn > lastSyncOn))
                            )
                            select new MobileRESTEntities.UserPreference
                            {
                                CreatedOn = (up == null) ? p.CreatedOn : up.CreatedOn,
                                UpdatedOn = (up == null) ? p.CreatedOn : (up.UpdatedOn ?? up.CreatedOn),
                                PreferenceId = p.PreferenceId,
                                Value = (up == null) ? p.ValueDefault : up.Value,
                            };
没有哪里好

SELECT 
[Extent1].[PreferenceKey] AS [PreferenceKey], 
CASE WHEN ([Extent2].[UserPreferenceKey] IS NULL) THEN [Extent1].[CreatedOn] ELSE [Extent2].[CreatedOn] END AS [C1], 
CASE WHEN ([Extent2].[UserPreferenceKey] IS NULL) THEN [Extent1].[CreatedOn] WHEN ([Extent2].[UpdatedOn] IS NULL) THEN [Extent2].[CreatedOn] ELSE [Extent2].[UpdatedOn] END AS [C2], 
[Extent1].[PreferenceId] AS [PreferenceId], 
CASE WHEN ([Extent2].[UserPreferenceKey] IS NULL) THEN [Extent1].[ValueDefault] ELSE [Extent2].[Value] END AS [C3]
FROM  [dbo].[MBLPreference] AS [Extent1]
LEFT OUTER JOIN [dbo].[MBLUserPreference] AS [Extent2] ON [Extent1].[PreferenceKey] = [Extent2].[PreferenceKey]
使用WHERE-BAD-无外部连接

exec sp_executesql N'SELECT 
[Extent1].[PreferenceKey] AS [PreferenceKey], 
[Extent2].[CreatedOn] AS [CreatedOn], 
CASE WHEN ([Extent2].[UpdatedOn] IS NULL) THEN [Extent2].[CreatedOn] ELSE [Extent2].[UpdatedOn] END AS [C1], 
[Extent1].[PreferenceId] AS [PreferenceId], 
[Extent2].[Value] AS [Value]
FROM  [dbo].[MBLPreference] AS [Extent1]
INNER JOIN [dbo].[MBLUserPreference] AS [Extent2] ON [Extent1].[PreferenceKey] = [Extent2].[PreferenceKey]
WHERE ([Extent2].[UserKey] = @p__linq__0) AND ((1 = 0) OR (([Extent2].[UpdatedOn] > @p__linq__1) AND ([Extent2].[UpdatedOn] IS NOT NULL)) OR ([Extent2].[CreatedOn] > @p__linq__2))',N'@p__linq__0 int,@p__linq__1 datetime2(7),@p__linq__2 datetime2(7)',@p__linq__0=15,@p__linq__1='0001-01-01 00:00:00',@p__linq__2='0001-01-01 00:00:00'
编辑

是的,WHERE将无法正常工作,但我的SQL应该如下所示:

SELECT P.*
FROM dbo.MBLPreference P
LEFT OUTER JOIN dbo.MBLUserPreference UP ON P.PreferenceKey = UP.PreferenceKey
AND UP.UserKey = 8 AND UP.CreatedOn > '1-1-1'
我应该如何编写LINQ来实现这一点

回答

这就是我需要做的(将条件移动到联接本身上)


我不确定您想要实现什么,但我相信您需要在
where
up:
上下文中p的
首选项
在context.UserPreferences.Where(x=>x.UserKey==user.ProviderUserKey&&
(//您的其他条件)
)
进入外。。。。

一个带WHERE的左外连接基本上是一个内连接,因此EF将其显式化。@RPM1984但如果我手动编写SQL,我可以实现我所需要的。我如何使它与EF一起工作?我不想运行2个查询,如果possible@RPM1984再次检查。你说对了,哪里就不行。如何实现我的主要帖子编辑中列出的SQL?编辑中的SQL和EF生成的结果是相同的。在联接上具有条件的左外部联接与条件为where的内部联接相同。结果集是否与您预期的不同?谢谢!这就是我需要的,我对语法不是很确定。我会更新主要帖子
var query = from p in context.Preferences
                            join up in context.UserPreferences
                            .Where(x => 
                                x.UserKey.Equals((int)user.ProviderUserKey)
                                &&
                                ((x.UpdatedOn > lastSyncOn && x.UpdatedOn != null) || (x.CreatedOn > lastSyncOn))
                                ) 
                            on p.PreferenceKey equals up.PreferenceKey into outer
                            from up in outer.DefaultIfEmpty() 
                            select new MobileRESTEntities.UserPreference
                            {
                                CreatedOn = (up == null) ? p.CreatedOn : up.CreatedOn,
                                UpdatedOn = (up == null) ? p.CreatedOn : (up.UpdatedOn ?? up.CreatedOn),
                                PreferenceId = p.PreferenceId,
                                Value = (up == null) ? p.ValueDefault : up.Value,
                            };