2012-06-15 105 views
3

設置一般屬性我有一個看起來像這樣多個查詢:如何使用LINQ選擇

var query = from a in EntityAs 
      select new EntityASmall() 
      { 
       // Common Stuff: 
       Id = a.Id, 
       Name = a.Name, 
       ShortName = a.ShortName, 
       // Specific to EntityA: 
       ASpecificProperty1 = a.1, 
       ASpecificProperty2 = a.2 
      }; 

var query = from b in EntityBs 
      select new EntityBSmall() 
      { 
       // Common Stuff: 
       Id = b.Id, 
       Name = b.Name, 
       ShortName = b.ShortName, 
       // Specific to EntityB: 
       BSpecificProperty1 = b.1, 
       BSpecificProperty2 = b.2 
      }; 

EntityA和EntityB都從具有IdNameShortName性質的公共基類派生。 EntityASmallEntityBSmall也一樣。我有很多看起來像這樣的查詢,所以我想做一些簡寫查詢,首先將常見的東西排除在外。我發現了一個有點前途的擴展方法,看起來像這樣:

public static TSource SetCommonProperties<TSource>(this TSource input, EntityBaseClass entity, Action<TSource> updater) where TSource : EntitySmallBase 
{ 
    input.Id = entity.Id; 
    input.Name = entity.Name; 
    input.ShortName = entity.Name; 

    updater(input); 

    return input; 
} 

我可以用它像這樣:

var query = from a in EntityAs.AsEnumerable() 
      select new EntityASmall().SetCommonProperties(a, x => 
      { 
       ASpecificProperty1 = x.1; 
       ASpecificProperty2 = x.2; 
      }); 

注意AsEnumerable()。沒有它,我得到「一個lambda表達式與一個語句正文不能轉換爲表達式樹」,我猜粗略的意思是它試圖將Action部分轉換爲LINQ到SQL的表達式。看起來像AsEnumerable()把它收集在本地的地方它的全部工作。對於長篇大論的文章感到抱歉,但是有沒有什麼表達式方法可以用來編寫可以與LINQ-to-SQL和Entity Framework一起使用的表達式?提前致謝。

+0

'EntityAs'是'IQueryable <>'? –

+0

難道你不能寫一個泛型方法'ProjectOntoSmall',它需要一個'TEntity'類型的參數並將其轉換爲'TEntitySmall'?如果你對這些類型參數施加約束,而這些參數必須從基類型中派生出來,那我想可能會起作用。 –

回答

0

你想出的擴展方法看起來不錯。

它只是你必須爲每個派生實體創建它,這可能是罰款,因爲你似乎有幾個dervied實體。

其次我不認爲你真的需要在你的擴展方法中傳遞那個動作委託。 如果可能,只需在那裏調用該方法。我對設計不太瞭解。

所以,你的擴展方法是這樣的

public static TSource SetCommonProperties<TSource>(this TSource input, EntityBaseClass entity)  where TSource : EntitySmallBase 
{ 
    input.Id = entity.Id; 
    input.Name = entity.Name; 
    input.ShortName = entity.Name; 

    this.Update(input); // Or this method could exist in any other class or static class. 

    return input; 

}

然後你就可以使用extesion方法如下爲好。

var query = from a in EntityAs 
     select new EntityASmall 
     {  
      ASpecificProperty1  
      ASpecificProperty2  
     }).SetCommonProperties(a,entity)  

這將消除您使用AsEnumerable的使用。 您還可以從你的基地轉變爲derviced方法用同樣的方法,如果你想這樣的:

DerivceEntityObject SetCommonProperties(BaseEntity) 

我希望這給你一個想法是什麼我想在這裏建議。

+0

Hm,適用於LINQ-to-SQL,但不適用於EF。它抱怨SetCommonProperties不能被轉換爲SQL。林猜測它適用於LINQ到SQL,因爲LINQ-to-SQL和LINQ-to-Objects之間的線條更加模糊。 – Ocelot20

+0

是的,我同意我錯過了EF的東西。它會抱怨,因爲它試圖翻譯SQL中的方法。在這種情況下,你可以做的是刪除這個keywork(沒有更多的擴展方法),並以我提到的相同方式將它用作一個常規方法。 – Tabish

+0

例如:對於一個EntityAs選擇SetCommonProperties(一個實體),然後照顧你正在做的事情。 – Tabish

1

你想讓自己的代碼變得乾乾淨淨,這總是很好用。也許你會用一些勞動和勞動以及一些巫術工作,但也許你會喜歡這個鏈接:Stop using AutoMapper in your Data Access Code。 (即使你不使用AutoMapper)。

通過這個漂亮的作品,你就可以編寫簡潔的語句,如:

context.EntityAs.Project().To<EntityASmall>(); 
context.EntityBs.Project().To<EntityBSmall>(); 

我這次真的用我自己和我喜歡它。

+0

尼斯鏈接。我喜歡它,但不幸的是它對任何東西都沒有幫助,只是非常簡單的映射。我需要一些更強大的東西。 – Ocelot20