2012-03-18 10 views
0

Entity Framework 4は、そうではないと思われるレコードを除外しています。子レコードが存在しない場合、Entity Framework(親レコードを除く)をRIA Servicesで使用するのはなぜですか?

表の定義

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と表2のレコードを持っている場合は、それらが期待通りに返されます

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

。私がテーブル1に関連するレコードをテーブル2に持っていなければ、そのレコードは除外されています。 Table_2でPriorityフィールドは、「そこにISNとき、それはある(nullの場合、

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

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

ので、本質的に:SQL Serverプロファイラを実行している際に

は、私は、エンティティフレームワークは、以下のCASTを追加したことに気づいたとWHERE句表2の親Tabe_1表に対応するレコード)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に応じて、いくつかは、すべての子供が親を持たなければならない多くの1つです。だから理論的には、あなたは親なしで子を持つことはできません。

親を持たない子を持つ場合は、関係は0または1対多であり、外部キーはNULL可能でなければなりません。

+0

これは本当にエンティティフレームワークの仕組みですか?私がやったほぼすべてのプロの仕事の中で、子供レコード(住所など)を持たない親レコード(人口統計など)がある状況が常にありました。私は、この状況を説明するために、エンティティ・フレームワークは、常に提供されるべき外部キーにNULLを許可する必要があると信じることが難しいと感じています。このタイプの違反が予想される場合、これは私の中核を傷つけます。これが正しいと確信していますか?どこかに書類を見たことがありますか? –

+0

子なしの親を持つことはできますが、親なしの子を持つことはできません。 –

0

私がEntity Frameworkを見たところでは、単一のIncludeは常に外部結合として変換されます。ただし、複数のインクルードの場合、インクルードの順序によって結合が内側か外側かが決まります。

あなたの例では、「Place」は外部結合されているとしますが、「EventInvitees」と「User」は両方とも内部結合されていると仮定します。 (少なくとも、私が似たような質問をしたときに起こることです)。

あなたは

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

「場所」に順序を変更したい場合は、内側参加されるだろうと「EventInvitees」外側は(私の同様のケースに基づいて、再び)に入社。

このMSDNの正確なロジックについてはドキュメントが見つかりませんので、結果は私のものと異なる場合があります。

+0

いいえ...実際には最初の大きなコードブロックをスクロールすると、すべてのテーブルが外部結合されていることがわかります(特に含まれていないが、エンティティの属性を使用しているユーザーテーブルは例外です)モデル)。私は注文を元に戻そうとしましたが、それは助けになりませんでした。同じフィルターが追加されます。 –

+0

ああ、はい、それを見落とした。私たちはここで試行錯誤しているように思えるのはちょっとイライラします。 –

+0

ええと...私はそれを回避することができますが、そうするためには、優先順位が必要であるというビジネスルールの実装に違反しなければなりません。私はクライアント側で強制することができますが、それは乱雑になります。ちょうど良い方法を探しています。あなたがそれを見てくれてありがとう。 –

関連する問題