2011-11-22 69 views
2

我有以下兩類:LINQ繼承「向下轉換」與新的物業

public class Base 
{ 
    public int Id { get; set; } 
    public string PropertyA { get; set; } 
} 

[NotMapped] 
public class Derived : Base 
{ 
    public string PropertyB { get; set; } 
} 

而且我有以下查詢:

var baseQ = from b in db.Bases 
      let propertyB = SomeCalculation() 
      select new { Base = b, PropertyB = propertyB }; 

此工程爲是。 我想是這樣的(僞代碼):

List<Derived> list = (from b in db.Bases 
         let propertyB = SomeCalculation() 
         select new { Base = b, PropertyB = propertyB }).ToList(); 

是否有可能以「向下轉換」的評選派生類,還是我寫派生類的一個構造函數,看起來是這樣的:

public Derived(Base b, string b) { ... } 

我的最終解決方案:我改變了派生類以下(因爲你甚至無法在對象初始使用的String.format):

public class Derived 
{ 
    public Base Base { get; set; } 
    public string PropertyB { get; set; } 

    public string CalculatedProperty { get { ... } }//For string.Format and other stuff 
} 

而且我做的assignement如下:

List<Derived> list = (from b in db.Bases 
         let propertyB = SomeCalculation() 
         select new Derived { Base = b, PropertyB = propertyB }).ToList(); 

回答

3

你不能因爲在你的查詢返回是一個匿名類型這種情況下施放。相反,你可以使用一個對象初始化設置屬性爲Derived類:

List<Derived> list = (from b in db.Bases 
        let propertyB = SomeCalculation() 
        select new Derived 
        { 
         Id = b.Id, 
         PropertyA = b.PropertyA, 
         PropertyB = propertyB 
        }).ToList(); 

如果你有一噸的屬性,你可以用你建議的方法,或添加數據傳輸對象(DTO),它包含您的屬性,然後使用像AutoMapper這樣的庫爲您執行映射。

+0

假設'db'是一個datacontext,這會拋出舊的'Can not constructor a'Derived',因爲這是一個非標量類型的錯誤。在執行選擇之前,您需要檢索「基礎」到集合。 –

+0

就我而言,DB是一個DbContext。 所以,這是行得通的。我將爲我的課程配置一個構造函數。對於這種簡單的情況,DTO似乎太多了。 :) – Shion

+0

@Kirk:你說得對!這不起作用。我以某種方式重讀了部分答案。那麼這種對象初始值設定器的方式呢? :) – Shion

1
List<Derived> list = db.Bases.ToList() 
.Select(p => new Derived() 
       { 
        Id = b.Id, 
        PropertyA = b.PropertyA, 
        PropertyB = SomeCalculation(), 
       }).ToList();; 
+0

這將返回一個空列表,因爲沒有'Bases'是'DerivedTypes' - 我們可以看到'DerivedType'實際上是一個帶有額外計算屬性的'Base'('let propertyB = SomeCalculation()') –

+0

@Kirk Broadhurst:你說得對,我編輯我的答案。 –

+1

雖然這個工作,它不是我所需要的。該計算使用來自Query內部的東西(它實際上不是一種方法)。另一件事是:這將選擇我的數據庫中的每個基地。不會很有效;)。 – Shion

0

接受的答案將不起作用,因爲EF不會讓您在數據庫中構造具體類型。解決方法 - 它允許您選擇匿名類型。

大廈艾哈邁德的回答是:

var aList = (from b in db.Bases 
      let propertyB = SomeCalculation() 
      select new 
      { 
       Id = b.Id, 
       PropertyA = b.PropertyA, 
       PropertyB = propertyB 
      }).ToList(); 

List<Derived> list = (from a in aList 
         select new Derived 
         { 
          Id = a.Id, 
          PropertyA = a.PropertyA, 
          PropertyB = a.PropertyB 
         }).ToList(); 

調用您的查詢ToList強制執行的查詢和數據被檢索到你的應用程序(即它將不再在數據庫中執行)。 aList現在是內存中的一個列表,因此您可以將這些項目選擇到新的Derived對象中。

用最簡單的術語來說,問題是直到你調用ToList的所有東西都被編譯成一個SQL查詢(以提高效率)。這通常是一件好事,但問題是您的數據庫沒有Derived的概念,並且查詢select new Derived無法轉換爲SQL。

+0

我同意你的意見。不幸的是,接受的答案也適用。它編譯,運行,並得到預期的結果。我將檢查該解決方案與新解決方案之間是否存在性能差異。謝謝。 – Shion

+0

@Shion如果它有效,那就去吧。我不認爲它會。 –

+0

是的,我會的。 :) – Shion