2012-07-17 44 views
2

我有兩個表的研究和系列。系列會返回到研究中,因此一項研究包含可變數量的系列。 每個系列項目有一個Deleted列表示它已從數據庫中邏輯刪除。如何在Linq-to-SQL實體類中創建自定義屬性?

我試圖在Study類中實現一個Deleted屬性,只有當所有包含的Series都被刪除時才返回true。 我使用O/R設計生成的類,所以增加了以下的用戶可修改的局部類研究類型:

public bool Deleted 
{ 
    get 
    { 
     var nonDeletedSeries = from s in Series 
           where !s.Deleted 
           select s; 
     return nonDeletedSeries.Count() == 0; 
    } 
    set 
    { 
     foreach (var series in Series) 
     { 
      series.Deleted = value; 
     } 
    } 
} 

這給出了一個異常「的成員‘PiccoloDatabase.Study.Deleted’沒有支持到SQL的轉換「。當執行這個簡單的查詢,調用獲得:

IQueryable<Study> dataQuery = dbCtxt.Studies; 
dataQuery = dataQuery.Where((s) => !s.Deleted); 
foreach (var study in dataQuery) 
{ 
    ... 
} 

在此基礎上http://www.foliotek.com/devblog/using-custom-properties-inside-linq-to-sql-queries/,我嘗試以下方法:

static Expression<Func<Study, bool>> DeletedExpr = t => false; 
public bool Deleted 
{ 
    get 
    { 
     var nameFunc = DeletedExpr.Compile(); 
     return nameFunc(this); 
    } 
    set 
    { ... same as before 
    } 
} 

我得到相同的異常,當運行查詢時,沒有支持翻譯成SQL。 ( lambda表達式的邏輯是無關緊要的 - 只是試圖通過例外。)

我是否缺少一些基本屬性或某些東西來允許轉換爲SQL?我已經閱讀了關於這個異常的大部分帖子,但是沒有任何內容看起來完全適合我的案例。

+0

不應該是nonDeletedSeries.Count()== 0? – Ruslan 2012-07-26 16:58:52

+0

@Ruslan - 是的,謝謝。固定。 – 2012-07-26 18:07:45

+0

錯誤發生在哪裏?在設置或獲得?就像「在以下20行代碼中存在錯誤,幫助我」不會給我們太多的幫助......異常的確切細節也是有益的 – 2012-07-26 18:14:27

回答

1

我相信LINQ到SQL的意義在於你的實體是爲你映射的,並且必須在數據庫中有相關性。看起來你正在嘗試混合使用LINQ到對象和LINQ到SQL。

如果Series表在數據庫中有一個Deleted字段,並且Study表沒有,但是您希望將邏輯Study.Deleted轉換爲SQL,那麼擴展將是一種可行的方法。

public static class StudyExtensions 
{ 
    public static IQueryable<study> AllDeleted(this IQueryable<study> studies) 
    { 
     return studies.Where(study => !study.series.Any(series => !series.deleted)); 
    } 
} 

class Program 
{ 
    public static void Main() 
    { 
     DBDataContext db = new DBDataContext(); 
     db.Log = Console.Out; 

     var deletedStudies = 
      from study in db.studies.AllDeleted() 
      select study; 

     foreach (var study in deletedStudies) 
     { 
      Console.WriteLine(study.name); 
     } 
    } 
} 

這是你「刪除研究」表達映射到SQL:

SELECT t0.study_id, t0.name 
FROM study AS t0 
WHERE NOT EXISTS(
    SELECT NULL AS EMPTY 
    FROM series AS t1 
    WHERE (NOT (t1.deleted = 1)) AND (t1.fk_study_id = t0.study_id) 
) 

或者你可以建立實際的表情,並將其注入到你的查詢,但是那是矯枉過正。

但是,如果Series和Study沒有數據庫中的Deleted字段,但僅在內存中,則需要先將查詢轉換爲IEnumerable,然後才能訪問Deleted屬性。但是這樣做會在應用謂詞之前將記錄轉移到內存中,並且可能會很昂貴。即

var deletedStudies = 
    from study in db.studies.ToList() 
    where study.Deleted 
    select study; 

foreach (var study in deletedStudies) 
{ 
    Console.WriteLine(study.name); 
} 
0

當您進行查詢時,您將要使用的靜態定義Expression,而不是財產。

有效,而不是:

dataQuery = dataQuery.Where((s) => !s.Deleted); 

當你正在一個LINQ to SQL查詢,你反而要使用:

dataQuery = dataQuery.Where(DeletedExpr); 

注意,這將需要你可以看到DeletedExprdataQuery,所以你需要將其移出課程或公開它(例如,使其成爲public,在這種情況下,您可以通過課程定義訪問它:Series.DeletedExpr)。

此外,Expression是有限的,因爲它不能有一個函數體。所以,DeletedExpr可能看起來像:

public static Expression<Func<Study, bool>> DeletedExpr = s => s.Series.Any(se => se.Deleted); 

的屬性添加爲方便起見,這樣就可以使用它作爲你的代碼的對象的一部分,而不需要重複的代碼,即

var s = new Study(); 
if (s.Deleted) 
    ... 
相關問題