簡體   English   中英

如何在Linq-to-SQL實體類中創建自定義屬性?

[英]How to create a custom property in a Linq-to-SQL entity class?

我有兩個表研究和系列。 系列是FK返回研究,因此一個研究包含可變數量的系列。 每個系列項目都有一個“ Deleted列,表示已從邏輯上將其從數據庫中刪除。

我試圖在Study類中實現Deleted屬性,該屬性僅在刪除所有包含的Series時才返回true。 我正在使用O / R Designer生成的類,因此將以下內容添加到了Study類型的用戶可修改的部分類中:

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轉換。” 執行此簡單查詢時,調用get:

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? 我已經閱讀了有關此異常的大多數SO帖子,但似乎完全不適合我的情況。

我相信LINQ-to-SQL的重點是為您映射了實體,並且必須在數據庫中具有關聯。 看來您正在嘗試混合使用LINQ-to-Objects和LINQ-to-SQL。

如果“系列”表在數據庫中具有“已刪除”字段,而“學習”表沒有,但是您想將邏輯“學習。刪除”轉換為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)
)

或者,您可以構建實際的表達式並將其注入查詢中,但這是一個過大的選擇。

但是,如果“系列”或“研究”都沒有數據庫中的“已刪除”字段,而僅在內存中,那么您需要首先將查詢轉換為IEnumerable,然后才訪問“已刪除”屬性。 但是,這樣做會在應用謂詞之前將記錄傳輸到內存中,並且可能會很昂貴。

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

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

查詢時,您將要使用靜態定義的Expression ,而不是屬性。

有效地,代替:

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

每當進行Linq to SQL查詢時,您都想使用:

dataQuery = dataQuery.Where(DeletedExpr);

請注意,這將要求您可以從dataQuery看到DeletedExpr ,因此您需要將其移出您的類,或者將其公開(即,將其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)
    ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM