2011-12-29 50 views
1

我的上下文模型有幾個相關的表:需要協助建立一個實體框架4查詢

CREATE TABLE "CarSystem"."Reads" (
    "ReadId"     UUID   PRIMARY KEY, 
    . . . 
); 

CREATE TABLE "CarSystem"."Alarms" (
    "AlarmId"     UUID   PRIMARY KEY DEFAULT UUID_GENERATE_V4(), 
    "ReadId"     UUID   NOT NULL REFERENCES "CarSystem"."Reads"     ("ReadId"), 
    . . . 
); 

還有其他列,但他們並不重要。 Reads表和Alarms表之間存在零關係。對於Reads表中的每行,Alarms表中可以有任意數量的行,從零開始。

我有這個數據庫結構的實體框架模型。我還爲Reads表中的行獲得了ViewModel對象。我希望ViewModel對象具有名爲HasAlarms的布爾屬性。如果Reads表中的行的Alarms表中至少有一行,則此屬性將設置爲true。

我在我的數據訪問層中有一個函數,它應該返回一個Read ViewModel對象的數組,這些對象都符合一組條件。我不知道如何構建查詢來設置HasAlarms屬性。我只想進入數據庫一次,並且我希望讀數表中的每一行都有一個入口。

現在,我做兩個數據庫查詢,一個檢索所有的讀取和另一檢索所有的報警:

IQueryable<Read> query = from read in context.Reads 
         where SomeCondition 
         select read; 

Alarm[] alarms = (from read in query 
        join alarm in context.Alarms on read.Readid equals alarm.ReadId 
        select alarm).ToArray(); 

ReadViewModel[] result = (from read in query 
          select new ReadViewModel { 
           ReadId = read.ReadId, 
           . . . 
           HasAlarms = alarms.Where(a => a.ReadId == read.ReadId).Any(), 
           . . . 
          }).ToArray();  

這工作,而是因爲我打的數據庫是低效兩次,一次檢索Reads表中的行,一次獲取Alarms。

有沒有辦法建立這個查詢,所以它只碰到數據庫一次?

託尼

@Craig斯頓茨:

我試圖做的是加快在該數據被加載在我的應用程序響應報告請求的速率。這是一個WPF應用程序,我需要儘快加載數據以改善用戶體驗。儘可能少地訪問數據庫或應用程序似乎要抓取很重要。

ReadViewModel對象由映射到表中的列的屬性以及存儲爲同一個表中的列或存儲在幾個相關表中的行中的幾個嵌套對象組成。這是一個複雜的結構,如果我試圖用一個IQueryable創建視圖模型對象,實體框架會抱怨。也就是說,這樣的:

ReadViewModel[] reads = (from read in context.Reads 
          join alarm in context.Alarms on read.ReadId equals alarm.ReadId 
          where SomeCondition 
          select new ReadViewModel { ... }).ToArray(); 

拋出,說實體框架不能創建嵌套類型的一個恆定的異常。

如果我將數據檢索到實體對象數組中,然後使用Linq創建視圖模型對象,那麼一切正常。但是,我不得不多次訪問數據庫才能獲得所有內容。但是,如果使用這些查詢檢索所有數據,它比讓Entity Framework返回並查詢每行的額外數據要快得多,當按照您的建議執行操作時會發生這種情況。還有一個複雜的情況是不得不使用Alarms表進行左外連接來搞砸。

我發現,如果我首先檢索實體對象的數組,而不是爲每行除了最初的旅程之外進行一次旅行,我總共可以進行2次或3次旅行。這比製作n + 1或n + 2旅行要快得多。我只是試圖看看是否有一種方法可以讓Entity Framework在一次數據庫調用中完成所有工作,如果我自己編寫SQL,那麼我可以輕鬆完成。如果Read的Alarms表中至少有一行,我只需添加一個爲HasAlarms返回0或1的列。

回答

3

在模型中使用導航/關係。 It's usually wrong to spell out joins in L2E

ReadViewModel[] result = (from read in context.Reads 
          where SomeCondition 
          select new ReadViwModel 
          { 
           ReadId = read.ReadId, 
           // . . . 
           HasAlarms = read.Alarms.Any(), 
           // . . . 
          }).ToArray();  
+0

Plesase看到我編輯原來的問題。 – 2011-12-30 15:46:08

+0

我給你的查詢在一次往返中獲取整個結果集。 – 2011-12-30 17:25:42