[英]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.