我的實體模型主要由6個實體組成,這些實體之間基於2個屬性進行連接。在LINQ to Entities中使用中間實體會導致System.NotSupportedException
我必須根據舊的純文本SQL查詢構建182個LINQ查詢。這些查詢有一些共同的部分,所以爲了避免重複,我已經構建了一個小框架來在構建塊之上構建查詢。我會馬上展示例子。由於所有查詢都是由6個實體的組合(從根實體SectionA
開始)之間的連接組成的,因此我爲了方便起見而構建了一個封裝類JoinOfSections
,它包裝了所有這些節。
在該類上,我可以執行所有182個查詢共有的簡單LINQ評估。
例如
public override IQueryable<QueryRow> Run(Models.auitool2014Entities dataContext, int aUserId, DateTime? dataInizioControllo, DateTime? dataFineControllo, string[] a52Exclude, bool codifiche2014)
string now = DateTime.Now.ToString("yyyyMMdd");
var sj = dataContext.sezione_a.SelectMany(
a => dataContext.sezione_d.Where(d => a.A03 == d.A03 && a.utente == d.utente).DefaultIfEmpty(),
(a, d) => new SezioneJoin { A = a, D = d });
sj = CommonFiltering(sj, aUserId, dataInizioControllo, dataFineControllo, a52Exclude);
return (from SezioneJoin ssj in sj
let a = ssj.A
let d = ssj.D
where
a.utente == aUserId &&
(
String.IsNullOrEmpty(a.A21) || String.IsNullOrEmpty(a.A51) ||
a.A51.CompareTo(a.A21) < 0 ||
a.A21.CompareTo(now) > 0 ||
a.A51.CompareTo(now) > 0 ||
a.A21.CompareTo("19000101") < 0 ||
a.A51.CompareTo("19000101") < 0
)
select ssj).Select(Select());
}
protected virtual IQueryable<SezioneJoin> CommonFiltering(IQueryable<SezioneJoin> sj, int aUserId, DateTime? dataInizioControllo, DateTime? dataFineControllo, string[] a52Exclude)
{
sj = sj.Where(x => x.A.utente == aUserId);
if (dataInizioControllo != null)
{
string dataInzio = dataInizioControllo.Value.ToString("yyyyMMdd");
sj = sj.Where(x => x.A.A21.CompareTo(dataInzio) >= 0);
}
if (dataFineControllo != null)
{
string dataFine = dataFineControllo.Value.ToString("yyyyMMdd");
sj = sj.Where(x => x.A.A21.CompareTo(dataFine) <= 0);
}
if (a52Exclude != null)
sj = sj.Where(x => !a52Exclude.Contains(x.A.A52));
return sj.Take(Parameters.ROW_LIMIT);
}
Select()
方法是一種常見的圖案的簡化。由於結果集必須才能被壓扁的舊組件來處理它,我發明了另一個適配器層
[Serializable]
public class QueryRow
{
public string A01 { get; set; }
public string A01a { get; set; }
public string A01b { get; set; }
public string A02 { get; set; }
public string A03 { get; set; }
public string A11 { get; set; }
public string A12 { get; set; }
// Dozens of string members
}
爲了不復制粘貼& ......
protected virtual Expression<Func<SezioneJoin, QueryRow>> Select()
{
return sj => new QueryRow
{
A01 = sj.A.A01,
A01a = sj.A.A01a,
A01b = sj.A.A01b,
A02 = sj.A.A02,
A03 = sj.A.A03,
A11 = sj.A.A11,
A12 = sj.A.A12,
A12a = sj.A.A12a,
A12b = sj.A.A12b,
A12c = sj.A.A12c,
A21 = sj.A.A21,
A22 = sj.A.A22,
A23 = sj.A.A23,
A24 = sj.A.A24,
A25 = sj.A.A25,
A31 = sj.A.A31,
A31a = sj.A.A31a,
A31b = sj.A.A31b,
A32 = sj.A.A32,
}
SezioneJoin
類代表數據集中的一行是多個實體之間的組合JOIN
,如下所示。它被設計,以便對任何查詢來實例化其定製JOIN(如A內d,左d左E,A內d左1H)
public class SezioneJoin
{
public SezioneA A { get; set; }
public SezioneD D { get; set; }
public SezioneE E { get; set; }
public SezioneF F { get; set; }
public SezioneG G { get; set; }
public SezioneH H { get; set; }
}
基本上所有查詢要求,該數據集上過濾當前用戶ID和可選檢查日期,再加上他們全部允許最大數量的結果。
我付出了我的企圖概括與NotSupportedException
概念(異常消息由我翻譯)
無法轉換類型「DiagnosticoSite.Data.Query.SezioneJoin」到 「DiagnosticoSite.Data.Query.SezioneJoin 」。 LINQ到實體支持 僅枚舉或原始EDM數據類型
問題可能在於(a, d) => new SezioneJoin { A = a, D = d }
線:如果我選擇匿名類型LINQ查詢工作得完美無缺,但然後我可以查詢對象不傳遞給受保護的方法,裝飾它與額外的常見檢查。
作爲他們的182個查詢,我很重要的是找到一種方法來爲所有查詢添加通用檢查,這些查詢不是而是拷貝&粘貼。
我想知道如何使用不在數據上下文中的「緩衝區」或「中間」實體來操作LINQ to Entities查詢,以便可以將查詢本身作爲複雜參數傳遞給參數裝飾者方法。
在枚舉和調用ToString()
方法的IQueryable方法返回Run
時會發生錯誤。我需要ToString來提取發給DB的查詢
該代碼應該工作。你能添加「SezioneJoin」的定義嗎?並且指定您正在使用的實體框架的版本。 –
可以肯定的是,你說你翻譯了異常信息。你確定該消息表明它不能將'DiagnosticoSite.Data.Query.SezioneJoin'轉換爲'DiagnosticoSite.Data.Query.SezioneJoin'(同一類型)嗎? –
這似乎是一個太晚實現實體的問題。我沒有詳細閱讀該問題,但LINQ-To-SQL的非模型類立即觸發了此警報。在調用ToList或以其他方式將SQL結果枚舉爲實際的.NET CLR對象之前,您不能選擇具有LINQ查詢的非模型對象,因爲LINQ引擎無法將您的代碼映射到查詢。我很可能是錯的,但是想增加我的2美分。 – Machinarius