0

Entity Framework 4는 필자가 그렇게 생각하지 않는 레코드를 제외하고 있습니다.자식 레코드가없는 경우 엔 Entity Framework (RIA 서비스 포함)가 부모 레코드를 제외하는 이유는 무엇입니까?

테이블 정의

Table_1 

    UniqueIdentifier ID not null 
    int AnotherField 

Table_2 

    UniqueIdentifier ID not null 
    UniqueIdentifier Table_1ID not null 
    int Priority not null 

table_1ID 필드를 통해 표 1과 표 2 사이의 관계가있다 : 여기 내 시나리오입니다. 그것은 데이터베이스에 정의되어 있으며 엔티티 프레임 워크는이를 인식합니다.

나는 나의 DomainService에 정의 된 쿼리가 예상대로 내가 표 1과 표 관련이있는 기록이있는 경우

private ObjectQuery<Table_1> Table_1WithIncludes()  
{   
    return this.ObjectContext.Table_1   
     .Include("Table_2")     
} 

을, 그들은 반환받을. 테이블 2에 레코드가 하나도없는 경우 레코드가 제외됩니다. Table_2의 우선 순위 필드가 null의 경우

CASE WHEN ([Join2].[Priority] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1] 

WHERE ([Project1].[C1] > 0) 

을 그래서 본질적으로, (가 외설이되는 경우 'SQL Server 프로파일 러를 실행하면

, 내가 엔티티 프레임 워크는 다음 CAST 및 조항이 곳을 추가 한 것으로 나타났습니다 부모 Tabe_1 테이블에 해당하는 표 2의 레코드) where 절은 두 레코드가 모두 삭제되도록합니다 (null> 0 실패).

이제 우선 순위 필드의 정의를 변경하지 않아도되므로 캐스트와 체크가 필요 없으며 모두 양호합니다. 그러나 나는 이것을해야만하는 것처럼 보이지 않는다.

내가 잘못 했습니까? 내 이해가 잘못 됐니?

전체 EntityQuery 및 생성 된 쿼리 텍스트는 도움이 될 수 있습니다.

private ObjectQuery<Event> EventsWithIncludes() 
    { 
     return this.ObjectContext.Events 
      .Include("Place") 
      .Include("EventInvitees") 
      .Include("EventInvitees.User"); 
    } 


exec sp_executesql N'SELECT 
[Project2].[NumberOfPeople] AS [NumberOfPeople], 
[Project2].[ID] AS [ID], 
[Project2].[CreatorID] AS [CreatorID], 
[Project2].[CreateDate] AS [CreateDate], 
[Project2].[PlacesID] AS [PlacesID], 
[Project2].[EventDate] AS [EventDate], 
[Project2].[EventTime] AS [EventTime], 
[Project2].[Availability] AS [Availability], 
[Project2].[EscalationLevels] AS [EscalationLevels], 
[Project2].[Rank] AS [Rank], 
[Project2].[RowVersion] AS [RowVersion], 
[Project2].[ID1] AS [ID1], 
[Project2].[Name] AS [Name], 
[Project2].[Phone] AS [Phone], 
[Project2].[DefaultPar] AS [DefaultPar], 
[Project2].[DefaultSlope] AS [DefaultSlope], 
[Project2].[DefaultRating] AS [DefaultRating], 
[Project2].[CreateDate1] AS [CreateDate1], 
[Project2].[UpdateDate] AS [UpdateDate], 
[Project2].[MetroAreaID] AS [MetroAreaID], 
[Project2].[C1] AS [C1], 
[Project2].[PriorityOrder] AS [PriorityOrder], 
[Project2].[ID2] AS [ID2], 
[Project2].[EventsID] AS [EventsID], 
[Project2].[InviteeUsersID] AS [InviteeUsersID], 
[Project2].[RowVersion1] AS [RowVersion1], 
[Project2].[Attending] AS [Attending], 
[Project2].[StatusChange] AS [StatusChange], 
[Project2].[ID3] AS [ID3], 
[Project2].[First] AS [First], 
[Project2].[Last] AS [Last], 
[Project2].[UserName] AS [UserName], 
[Project2].[Password] AS [Password], 
[Project2].[Gender] AS [Gender], 
[Project2].[Email] AS [Email], 
[Project2].[Email_Sharing] AS [Email_Sharing], 
[Project2].[Email_Receive] AS [Email_Receive], 
[Project2].[Phone1] AS [Phone1], 
[Project2].[Phone_Sharing] AS [Phone_Sharing], 
[Project2].[Phone_Receive] AS [Phone_Receive], 
[Project2].[CreateDate2] AS [CreateDate2], 
[Project2].[UpdateDate1] AS [UpdateDate1] 
FROM (SELECT 
    [Project1].[ID] AS [ID], 
    [Project1].[CreatorID] AS [CreatorID], 
    [Project1].[CreateDate] AS [CreateDate], 
    [Project1].[NumberOfPeople] AS [NumberOfPeople], 
    [Project1].[PlacesID] AS [PlacesID], 
    [Project1].[EventDate] AS [EventDate], 
    [Project1].[Availability] AS [Availability], 
    [Project1].[EscalationLevels] AS [EscalationLevels], 
    [Project1].[Rank] AS [Rank], 
    [Project1].[RowVersion] AS [RowVersion], 
    [Project1].[EventTime] AS [EventTime], 
    [Extent3].[ID] AS [ID1], 
    [Extent3].[Name] AS [Name], 
    [Extent3].[Phone] AS [Phone], 
    [Extent3].[DefaultPar] AS [DefaultPar], 
    [Extent3].[DefaultSlope] AS [DefaultSlope], 
    [Extent3].[DefaultRating] AS [DefaultRating], 
    [Extent3].[CreateDate] AS [CreateDate1], 
    [Extent3].[UpdateDate] AS [UpdateDate], 
    [Extent3].[MetroAreaID] AS [MetroAreaID], 
    [Join2].[ID1] AS [ID2], 
    [Join2].[EventsID] AS [EventsID], 
    [Join2].[InviteeUsersID] AS [InviteeUsersID], 
    [Join2].[PriorityOrder] AS [PriorityOrder], 
    [Join2].[RowVersion] AS [RowVersion1], 
    [Join2].[Attending] AS [Attending], 
    [Join2].[StatusChange] AS [StatusChange], 
    [Join2].[ID2] AS [ID3], 
    [Join2].[First] AS [First], 
    [Join2].[Last] AS [Last], 
    [Join2].[UserName] AS [UserName], 
    [Join2].[Password] AS [Password], 
    [Join2].[Gender] AS [Gender], 
    [Join2].[Email] AS [Email], 
    [Join2].[Email_Sharing] AS [Email_Sharing], 
    [Join2].[Email_Receive] AS [Email_Receive], 
    [Join2].[Phone] AS [Phone1], 
    [Join2].[Phone_Sharing] AS [Phone_Sharing], 
    [Join2].[Phone_Receive] AS [Phone_Receive], 
    [Join2].[CreateDate] AS [CreateDate2], 
    [Join2].[UpdateDate] AS [UpdateDate1], 
    CASE WHEN ([Join2].[PriorityOrder] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1] 
    FROM (SELECT 
     [Extent1].[ID] AS [ID], 
     [Extent1].[CreatorID] AS [CreatorID], 
     [Extent1].[CreateDate] AS [CreateDate], 
     [Extent1].[NumberOfPeople] AS [NumberOfPeople], 
     [Extent1].[PlacesID] AS [PlacesID], 
     [Extent1].[EventDate] AS [EventDate], 
     [Extent1].[Availability] AS [Availability], 
     [Extent1].[EscalationLevels] AS [EscalationLevels], 
     [Extent1].[Rank] AS [Rank], 
    [Extent1].[RowVersion] AS [RowVersion], 
    [Extent1].[EventTime] AS [EventTime], 
    (SELECT 
     COUNT(1) AS [A1] 
     FROM [dbo].[EventInvitees] AS [Extent2] 
     WHERE ([Extent1].[ID] = [Extent2].[EventsID]) AND ([Extent2].[InviteeUsersID] = @p__linq__2)) AS [C1] 
    FROM [dbo].[Events] AS [Extent1]) AS [Project1] 
LEFT OUTER JOIN [dbo].[Places] AS [Extent3] ON [Project1].[PlacesID] = [Extent3].[ID] 
LEFT OUTER JOIN (SELECT [Extent4].[ID] AS [ID1], [Extent4].[EventsID] AS [EventsID], [Extent4].[InviteeUsersID] AS [InviteeUsersID], [Extent4].[PriorityOrder] AS [PriorityOrder], [Extent4].[RowVersion] AS [RowVersion], [Extent4].[Attending] AS [Attending], [Extent4].[StatusChange] AS [StatusChange], [Extent5].[ID] AS [ID2], [Extent5].[First] AS [First], [Extent5].[Last] AS [Last], [Extent5].[UserName] AS [UserName], [Extent5].[Password] AS [Password], [Extent5].[Gender] AS [Gender], [Extent5].[Email] AS [Email], [Extent5].[Email_Sharing] AS [Email_Sharing], [Extent5].[Email_Receive] AS [Email_Receive], [Extent5].[Phone] AS [Phone], [Extent5].[Phone_Sharing] AS [Phone_Sharing], [Extent5].[Phone_Receive] AS [Phone_Receive], [Extent5].[CreateDate] AS [CreateDate], [Extent5].[UpdateDate] AS [UpdateDate] 
    FROM [dbo].[EventInvitees] AS [Extent4] 
    INNER JOIN [dbo].[Users] AS [Extent5] ON [Extent4].[InviteeUsersID] = [Extent5].[ID]) AS [Join2] ON [Project1].[ID] = [Join2].[EventsID] 
WHERE ([Project1].[C1] > 0) AND ([Project1].[CreatorID] = @p__linq__0) AND (([Project1].[EventDate] IS NULL) OR ([Project1].[EventDate] >= @p__linq__1)) 
) AS [Project2] 
ORDER BY [Project2].[ID] ASC, [Project2].[ID1] ASC, [Project2].[C1] ASC',N'@p__linq__2  uniqueidentifier,@p__linq__0 uniqueidentifier,@p__linq__1 datetime2(7)',@p__linq__2='33BB8199-7B25-4B3A-B96D-044EB7DB70AE',@p__linq__0='33BB8199-7B25-4B3A-B96D-044EB7DB70AE',@p__linq__1='1900-01-01 00:00:00' 

테이블 정의

USE [TheGreen18] 
GO 

/****** Object: Table [dbo].[EventInvitees] Script Date: 03/17/2012 22:27:16 ******/ 
SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE TABLE [dbo].[EventInvitees](
    [ID] [uniqueidentifier] NOT NULL, 
    [EventsID] [uniqueidentifier] NOT NULL, 
    [InviteeUsersID] [uniqueidentifier] NOT NULL, 
    [PriorityOrder] [int] NOT NULL, 
    [RowVersion] [timestamp] NULL, 
    [Attending] [bit] NULL, 
    [StatusChange] [datetime] NULL, 
CONSTRAINT [PK_EventInvitees] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[EventInvitees] WITH CHECK ADD CONSTRAINT [FK_EventInvitees_Events] FOREIGN KEY([EventsID]) 
REFERENCES [dbo].[Events] ([ID]) 
ON DELETE CASCADE 
GO 

ALTER TABLE [dbo].[EventInvitees] CHECK CONSTRAINT [FK_EventInvitees_Events] 
GO 

ALTER TABLE [dbo].[EventInvitees] WITH CHECK ADD CONSTRAINT [FK_EventInvitees_Users] FOREIGN KEY([InviteeUsersID]) 
REFERENCES [dbo].[Users] ([ID]) 
GO 

ALTER TABLE [dbo].[EventInvitees] CHECK CONSTRAINT [FK_EventInvitees_Users] 
GO 

답변

0

외국 키가 null 이외 할 수있는 경우는, 당신의 관계는 EF에 따라, 일부는 모든 어린이가 부모가 있어야 많은 하나입니다. 그래서 이론적으로 당신은 부모없는 아이를 가질 수 없습니다.

부모가없는 자식을 갖고 싶다면 관계가 0 또는 1 대 다수이고 외래 키가 null이어야합니다.

+0

엔티티 프레임 워크가 실제로 작동하는 방식입니까? 내가 한 거의 모든 전문직에서는 자녀 기록 (주소 등)이없는 부모 기록 (인구 통계와 같은)이있는 경우가 항상있었습니다. 이 상황을 설명하기 위해 엔티티 프레임 워크는 항상 제공되어야하는 외래 키에서 null을 허용해야한다고 믿는 것이 어렵습니다. 이러한 유형의 위반이 예상되는 경우 내 핵심이 아플 수 있습니다. 이게 옳은 거니? 어딘가에서 문서를 본 적이 있습니까? –

+0

자녀가없는 부모를 가질 수는 있지만 부모가없는 자녀는 가질 수 없습니다. –

0

Entity Framework에서 본 하나의 Include은 항상 외부 조인으로 변환됩니다. 그러나 여러 Include를 사용하면 포함 순서에 따라 조인이 내부인지 외부인지가 결정됩니다.

예제에서 "Place"는 외부 조인 인 반면 "EventInvitees"와 "User"는 내부 조인이라고 가정합니다. (적어도 비슷한 쿼리를 수행 할 때 일어나는 현상). 당신이

.Include("EventInvitees") 
.Include("EventInvitees.User") 
.Include("Place") 

"장소"로 순서를 변경한다면

합류 "EventInvitees"외부에 합류 내부 될 것이다 (다시, 내 비슷한 경우에 따라).

MSDN에서 정확한 논리에 대한 설명서를 찾을 수 없으므로 결과가 내 것과 다를 수 있습니다.

+0

아니 .... 실제로 처음 큰 코드 블록에서 스크롤하면 모든 테이블이 외부 조인 된 것을 볼 수 있습니다 (특별히 포함되지 않지만 엔티티의 특성을 사용하여 수행되는 사용자 테이블은 예외입니다) 모델). 주문을 취소하려했지만 도움이되지 않았습니다. 동일한 필터가 추가됩니다. –

+0

아, 그래, 그 하나를 간과. 우리가 여기서 시행 착오로 남겨지는 것처럼 보이는 것은 조금 실망 스럽습니다. –

+0

그래 ... 나는 그걸 해결할 수 있지만 그렇게하기 위해서는 우선 순위가 필요하다는 비즈니스 규칙의 구현을 위반해야한다. 클라이언트 쪽에서 시행 할 수는 있지만 엉망이됩니다. 더 나은 방법을 찾고 있습니다. 그래도 당신을 보아 주셔서 감사합니다. –