2012-05-18 104 views
-2

我想填充LINQ包含嵌套類數組的實例。我已經設法用下面的LINQ來做到這一點。我還包括組成該實例的類。在Linq選擇嵌套數組

select new EditableWarrantBook { 
     Id = p1.id, 
     Comment = p1.EntryComment, 
     WarrantYear1 = new BookYear { 
      StatusYear = p2.StatusYear, 
      Status = p2.Status, 
     }, 
     WarrantYear2 = new BookYear { 
      StatusYear = p3.StatusYear, 
      Status = p3.Status, 
     }, 
     WarrantYear3 = new BookYear { 
      StatusYear = p4.StatusYear, 
      Status = p4.Status, 
     } 
    } 

public class EditableWarrantBook 
{ 
    public int Id { get; set; } 
    public string Comment { get; set; } 

    public BookYear[] WarrantYear = new BookYear[3]; 

    public BookYear WarrantYear1 
    { 
     get { return WarrantYear[0]; } 
     set { WarrantYear[0] = value; } 
    } 
    public BookYear WarrantYear2 
    { 
     get { return WarrantYear[1]; } 
     set { WarrantYear[1] = value; } 
    } 
    public BookYear WarrantYear3 
    { 
     get { return WarrantYear[2]; } 
     set { WarrantYear[2] = value; } 
    } 

} 

public class BookYear 
{ 
    public int? StatusYear { get; set; } 
    public string Status { get; set; } 
} 

這工作我可與WarrantYear[0]WarrantYear1訪問值。這在設計UI時有時會很有用。但是,在這種情況下,我不需要WarrantYear1屬性,因爲我將其轉換爲JSON,並且不需要重複(或者想要在網絡上發送相同數據的兩個版本)。我的問題是,如何編寫select語句來加載WarrantYear數組。或者,我該如何編寫該類,以便可以將該數組作爲屬性訪問。我的解決方案不應包含EditableWarrantBook類中的Warrant1, Warrant2, Warrant3屬性。

+0

什麼是你想與所有的連接完成 - 他們都不是實際使用從CookSaleStatus對象的任何值... –

+0

的加入不是問題的一部分,但我根據您的評論簡化了一些。我不想混淆的東西,但有時候也不會混淆。 – ricardo

回答

0

問題是,你正試圖將SQL世界(構建你的查詢)與你的CLR世界混合(創建新對象)。解決這個問題的方法是將您的查詢分解爲您的初始數據提取查詢(SQL世界),然後枚舉結果以轉換爲您的對象(CLR世界):

因此,在where p1.SaleYear == 2009之後,添加此:

select new { p1, p2, p3, p4 }) 
.AsEnumerable() 
.Select(tr => new EditableWarrantBook 
    { 
    Id = tr.p1.id, 
    Comment = tr.p1.EntryComment, 
    WarrantYear = new[] { 
     tr.p2 == null ? (BookYear)null : new BookYear // EDITED LINE 
     { 
      StatusYear = tr.p2.StatusYear, 
      Status = tr.p2.Status, 
     }, 
     tr.p3 == null ? (BookYear)null : new BookYear // EDITED LINE 
     { 
      StatusYear = tr.p3.StatusYear, 
      Status = tr.p3.Status, 
     }, 
     tr.p4 == null ? (BookYear)null : new BookYear // EDITED LINE 
     { 
      StatusYear = tr.p4.StatusYear, 
      Status = tr.p4.Status, 
     }} 
    }).ToList(); 

如果你想留在查詢語法,然後只需將其更改爲:

result = from tr in 
    (/*Select up to the AsEnumerable call above)*/).AsEnumerable() 
    select new EditableWarrantBook 
     { 
      /* Initialization code supplied above */ 
     } 

編輯:所以,我已經修改了例如一個更多的時間。它看起來像你回來的價值之一是空的,所以我已經添加了空檢查,以確保你沒有訪問空對象的屬性(雖然我沒有檢查爲空p1)。

+0

我試過上面的代碼並編譯,但是我得到了下面的運行時錯誤。 「數組類型BookYear []無法在查詢結果中初始化,請考慮使用'System.Collecions.Generic.List'1 [blabla.BookYear]'。」這條消息對我沒有幫助。 – ricardo

+0

@ricardo - 基於這個回覆http://stackoverflow.com/questions/6435520/not-able-to-return-jsonresult似乎你可以使用'.AsEnumerable()'來解決這個問題 - 嘗試'從p4在list3.DefaultIfEmpty()。AsEnumerable()'? –

+0

沒有幫助,相同的錯誤消息。我的其他選擇是保持原樣並嘗試創建基準類,其中Warrant1,Warrant2和Warrant3受保護。然後使用一個可以掩蓋受保護屬性的子類,並使用它來創建JSON。但我也無法弄清楚,這就是爲什麼我想獲得幫助。我似乎在整體上越來越深入。謝謝你的幫助。 – ricardo

1

由於我無法讓選擇工作沒有Warrant1,Warrant2和Warrant3屬性,我將它保留原樣並重寫了該類,以便JSON序列化程序將創建沒有Warrant1,Warrant2和Warrant3屬性的JSON實例。文章中使用了this的反思。爲了澄清問題,我第一次嘗試創建的JSON有效負載是原來的兩倍,因爲JSON序列化器同時創建了Warrant1,Warrant2和Warrant3結構以及Warrant []數組。用只有Warrant []數組的JSON結果的基類重寫該類才能滿足Web服務的接口要求。

namespace my.Models 
{ 
public class WarrantBook 
{ 
    public int Id { get; set; } 
    public string Comment { get; set; } 

    BookYear[] warrantYear = new BookYear[3]; 

    public BookYear[] WarrantYear 
    { 
     get { return warrantYear; } 
     set { warrantYear = value; } 
    } 
} 

public class EditableWarrantBook : WarrantBook 
{ 
    public BookYear WarrantYear1 
    { 
     get { return WarrantYear[0]; } 
     set { WarrantYear[0] = value; } 
    } 
    public BookYear WarrantYear2 
    { 
     get { return WarrantYear[1]; } 
     set { WarrantYear[1] = value; } 
    } 
    public BookYear WarrantYear3 
    { 
     get { return WarrantYear[2]; } 
     set { WarrantYear[2] = value; } 
    } 

} 
public class BookYear 
{ 
    public int? StatusYear { get; set; } 
    public string Status { get; set; } 
} 

public static class Ext 
{ 
    public static void CopyProperties(this EditableWarrantBook source, WarrantBook destination) 
    { 
     // Iterate the Properties of the destination instance and 
     // populate them from their source counterparts 
     PropertyInfo[] destinationProperties = destination.GetType().GetProperties(); 
     foreach (PropertyInfo destinationPi in destinationProperties) 
     { 
      PropertyInfo sourcePi = source.GetType().GetProperty(destinationPi.Name); 
      destinationPi.SetValue(destination, sourcePi.GetValue(source, null), null); 
     } 
    } 
} 

}

使用WCF REST web服務

 [WebGet(UriTemplate = "GetWarrant?id={s}&user={user}")] 
    public WarrantBook GetWarrant(string s, string user) 
    { 
     int id; 
     if (int.TryParse(s, out id)) 
     { 
      EditableWarrantBook model = SessionWarrantBook.One(p => p.Id == id); 
      model.CheckedOutBy = user; // need to add checkout code 
      WarrantBook jsonModel = new WarrantBook(); 
      model.CopyProperties(jsonModel); 
      return jsonModel; 
     } 
     return new WarrantBook(); 
    }