2013-10-12 50 views
1

我有以下功能通過與動態LINQ對象循環聯接

public List<Object> GetEventsForAdmin() 
    { 
     using (var dbEntities = new CapeledEntities()) 
     { 
      return (from e in dbEntities.Events 
        join lnk in dbEntities.linkEventCategories on e.EventId equals lnk.EventId 
        join cat in dbEntities.Categories on lnk.CategoryId equals cat.CategoryId 
        orderby e.StartDateTime descending 
        select new { 
            e.EventId, 
            EventTitle = e.Title, 
            e.StartDateTime, 
            e.Description, 
            CatTitle = cat.Title 
        } 
      ).ToList<Object>(); 
     } 
    } 

我使用

var eventHelper = new BusinessLogic.DatabaseAccess.Helpers.BLEvents(); 
    foreach (var myEvent in eventHelper.GetEventsForAdmin()) 
    { 
     txtTitle.text = myEvent.CatTitle; 
     txtDescription.text = myEvent.description; 
    } 

然而myEvent.CatTitle和myEvent.description不哎呀發現

} 
+0

您已將返回的匿名類型列表轉換爲對象。 foreach循環中的代碼不知道它們是什麼。你可以嘗試foreach(動態myEvent在...)而不是var。編譯器會接受你放在myEvent之後的任何東西。 ,但如果它不存在於匿名類型的對象上,則會在運行時抱怨。 – Baldrick

+0

'GetEventsForAdmin'中每個元素的實際類型是**匿名類型**,您無法訪問其範圍之外的匿名類型對象。這不是'動態的' –

回答

2

更改

foreach (var myEvent in eventHelper.GetEventsForAdmin()) 

foreach (dynamic myEvent in eventHelper.GetEventsForAdmin()) 

這應該允許您訪問已被強制轉換爲對象的匿名類型的成員。

2

而不是使用dynamic的,我建議你創建一個簡單的structclass這樣的:

class Event 
{ 
    public int EventId; 
    public string EventTitle; 
    public DateTime StartDateTime; 
    public string Description; 
    public string CatTitle; 
} 

現在不是在你的LINQ做select new,您可以創建一個良好定義的類型,這將使你編碼的優勢以及性能提升becuz沒有拳擊/拆箱將涉及。

你的LINQ將被:

public List<Event> GetEventsForAdmin() 
{ 
    using (var dbEntities = new CapeledEntities()) 
    { 
     return (from e in dbEntities.Events 
       join lnk in dbEntities.linkEventCategories on e.EventId equals lnk.EventId 
       join cat in dbEntities.Categories on lnk.CategoryId equals cat.CategoryId 
       orderby e.StartDateTime descending 
       select new Event() { 
           .EventId = e.EventId, 
           .EventTitle = e.Title, 
           .StartDateTime = e.StartDateTime, 
           .Description = e.Description, 
           .CatTitle = cat.Title 
       } 
     ).ToList(); 
    } 
} 
+0

有關性能的有效點。在編譯時還提供了在成員訪問代碼中發現拼寫錯誤的額外優點! – Baldrick

+0

我同意你的建議,但不是出於性能原因。這是編譯時與運行時類型檢查。請參閱Mark對http:// stackoverflow的評論。com/questions/191013/can-ac-sharp-anonymous-class-implement-an-interface:「匿名類型的使用通常應限於lambda和LINQ表達式......只要數據暴露給調用者需要對對象「做點什麼」,它是一個非常好的主意,可以實現具體的類「 –

+0

性能原因與intellisense的好處一樣有效。這正是Mark發表的評論實際上意味着什麼。 – dotNET

1

看來有三種可能的方式,據我所知。

1)使用Dynamic(需要.NET 4.0或更高版本)

foreach (dynamic myEvent in eventHelper.GetEventsForAdmin())

2)創建自己的類型(也許是一類),而不是anonymous type

3)第三個是一個棘手其中一個使用CastByExample,你可以找到here

object obj = eventHelper.GetEventsForAdmin(); 
var events = CastByExample(obj, new[] { 
            new { EventId = 0, 
              EventTitle = "", 
              StartDateTime = DateTime.MinValue, 
              Description = "", 
              CatTitle = "" 
             } 
             }.ToList()); 
foreach (var item in events) 
{ 
    Console.WriteLine(item.EventId); 
} 

private static T CastByExample<T>(object obj, T example) 
{ 
    return (T)obj; 
} 

4)@KingKing在評論中建議我錯過了Reflection你也可以通過反射來做到這一點,但這對於這個問題並不是一個好主意。

被說盡可能多的方法可用,我會建議方法2是這個問題的理想解決方案。

+0

第四種方法是使用「反射」。 –

+0

@KingKing哎呀我錯過了,但'動態'已經涵蓋它不是嗎? –

+0

它可能會這樣做,但使用'Reflection'有不同的方法,您仍然可以使用.NET 3.5來實現,而動態需要.NET 4.0或更高版本。 –