2014-07-03 35 views
3

我一定要失去我的心......請看看下面的 enter image description here投影條件判斷錯誤

現在看的價值觀,我正在上查詢: enter image description here enter image description here

你可以看到ETouchesEvent爲空,事件不是......那麼爲什麼Linq to SQL認爲ETouchesEvent不爲null?我的第一張照片中的每個結果應該是1。

[更新] 下面是生成的T-SQL中,你可以清楚地看到,它使用ENTITYID檢查null

{SELECT 
    (CASE 
     WHEN ([t5].[EntityID]) IS NULL THEN @p1 
     WHEN ([t5].[EntityID]) IS NULL THEN @p2 
     ELSE @p3 
    END) AS [value] 
FROM (
    SELECT [t4].[ParticipationItemID], [t4].[EntityID] 
    FROM (
     SELECT [t0].[ParticipationItemID], [t0].[IsLocalEvent], [t0].[IsProject], [t0].[IsOther], [t0].[EntityID], [t0].[IsEtouchesEvent] 
     FROM [ParticipationItem] AS [t0] 
     INNER JOIN [dbo].[Event] AS [t1] ON [t0].[EntityID] = ([t1].[Id]) 
     WHERE [t0].[IsLocalEvent] = 1 
     UNION 
     SELECT [t2].[ParticipationItemID], [t2].[IsLocalEvent], [t2].[IsProject], [t2].[IsOther], [t2].[EntityID], [t2].[IsEtouchesEvent] 
     FROM [ParticipationItem] AS [t2] 
     INNER JOIN [ETouchesEvent] AS [t3] ON [t2].[EntityID] = ([t3].[ETouchesEventID]) 
     WHERE [t2].[IsEtouchesEvent] = 1 
     ) AS [t4] 
    ) AS [t5] 
WHERE ((([t5].[EntityID]) IS NOT NULL) OR (([t5].[EntityID]) IS NOT NULL)) AND (EXISTS(
    SELECT NULL AS [EMPTY] 
    FROM [OrganisationParticipation] AS [t6] 
    WHERE (([t6].[OrganisationID]) = @p0) AND ([t6].[ParticipationitemID] = ([t5].[ParticipationItemID])) 
    )) 
} 

這是所有代碼:

public List<int> GetParticipationYears(int? organisationID) 
    { 
     var result = (from p in GetParticipation(organisationID, null) 
       where p.ETouchesEvent != null || p.Event != null 
       select p.ETouchesEvent == null ? 1 : (p.Event == null ? 5 : 0)); 
       //select p.IsEtouchesEvent ? p.ETouchesEvent.StartDate.Year : (p.IsLocalEvent ? p.Event.StartDate.Year : 0)); //<== this does work! 
     return result.Distinct().ToList(); 
    } 

    public IQueryable<ParticipationItem> GetParticipation(int? organisationID, List<int> filterByYears) 
    { 
     var result = (from pi in DB.ParticipationItems 
         join e in DB.Events on pi.EntityID equals e.Id 
         where pi.IsLocalEvent 
         select pi) 
        .Union(
         from pi in DB.ParticipationItems 
         join e in DB.ETouchesEvents on pi.EntityID equals e.ETouchesEventID 
         where pi.IsEtouchesEvent 
         select pi); 

     if (filterByYears != null) 
      result = result.Where(pi => (pi.IsEtouchesEvent && pi.ETouchesEvent != null && filterByYears.Contains(pi.ETouchesEvent.StartDate.Year)) || 
             (pi.IsLocalEvent && pi.Event != null && filterByYears.Contains(pi.Event.StartDate.Year))); 

     if (organisationID.HasValue) 
      return result.Where(pi => pi.OrganisationParticipations.Any(x => x.OrganisationID == organisationID)); 
     else 
      return result; 
    } 
+0

我懷疑這是因爲這兩個屬性都是使用相同ID字段的關聯。例如它們都使用「EntityID」鏈接。我懷疑Linq-to-sql將其轉換爲ISNULL(EntityID),而不是檢查是否有可用的記錄 – Peter

+0

這可能是一個調試器工件。嘗試移動'.ToList()'上面的一行。當你調試時,跳過第一行(現在用'。ToList()'),只有當你到達第二行時(現在只是'return result;'),纔將鼠標懸停在鼠標上。 –

+0

@BrankoDimitrijevic非常感謝您的建議。我只是試過了,但它給了我相同的結果......我現在正在考慮這是Linq to SQL中的一個錯誤。 – Peter

回答

0

我沒有找到關於這種行爲的任何文件,但它似乎LINQ到SQL翻譯看外鍵列的背後關係(在這種情況下是EntityID)來查看它是否爲空而不是鏈接的記錄。生成的SQL清楚地顯示了這一點。

0

好的。

所以問題可能來自您的聯盟。

聯盟的所有部分必須共享相同數量的字段(具有相同類型)。

在你的情況下,聯盟的工作原理是因爲EventsETouchesEvents必須從同一個類繼承,或者實現相同的接口,或者只是相同。

但是,由該聯合生成的SQL不能使這兩種類型之間的區別(CASE當生成不會做你所需要的,這是「一致的」)。

所以你必須檢查一些sql可以區分的東西,這似乎只有IsLocalEventIsEtouchesEvent

所以(如果我錯了改變邏輯)

var result = (from p in GetParticipation(organisationID, null) 
       // don't need a where clause, you're doing a join in your union, so any returned part will have an event (which might be a EtouchesEvent or an Event 
       select !p.IsEtouchesEvent 
         ? 1 
         : !p.IsLocalEvent 
          ? 5 
          : 0); 

我同意,這是不直觀可言,但有時你不得不認爲「SQL」,不僅是「奧姆」。

如果你使用扁平物體,而不是這種情況下的實體,它可能會更清晰。

稍微多點。 聯合後,pi.ETouchesEvent上的任何測試都會生成與pi.Event完全相同的sql(並且它們不能爲空)。

所以,我想你也可以改變一年測試

if (filterByYears != null) 
      result = result.Where(pi => filterByYears.Contains(pi.ETouchesEvent.StartDate.Year);