2013-11-25 42 views
6

我對LINQ to Entities比較陌生,但使用LINQ to SQL很多。無法轉換爲LINQ to Entities存儲表達式

我使用Visual Studio 2013的EntityFramework 6和MVC 5.

兩者之間最大的區別是,LINQ2SQL具有執行SELECT查詢本身,而LINQ2Entities內部轉換的能力是不能容忍的,必須有在執行LINQ查詢之前進行正確的轉換。因此,我收到錯誤:類型'BillYeagerDB.EdmxExtensionMethods'中的指定方法'System.Decimal ConvertToDecimal(Byte)'無法轉換爲LINQ to Entities存儲表達式。

在做了大量的研究後,特別是在stackoveflow這個問題上,我發現了一個鏈接(LINQ to Entities does not recognize the method 'Double Parse(System.String)' method, and this method cannot be translated into a store expression),希望能起作用。我確信作者給出的例子是作品,但他正在使用ObjectContext,並且正在使用DbContext。

我也確定它會適用於我,但我想我只是錯誤地設計了擴展方法(這給了我上面的錯誤)。請注意,此特定問題與Linq查詢中的AvgRating變量有關。一旦我能夠實現這一點,我可以爲其他轉換進行相同類型的修復。請注意,AvgRating定義爲Decimal類型,a.Rating.RatingValue定義爲Byte類型。

如果有人能把我弄明白這一點,我將不勝感激。

這是我的代碼。我正在嘗試使用以下查詢,由於轉換問題,我知道這種查詢不起作用(如前所述)。

原始LINQ查詢:

namespace BillYeagerDB 
{ 
    public class BillYeagerDB 
    { 
     public async Task<List<RestaurantList>> GetRestaurantListAsync() 
     { 
      try 
      { 
       using (BillYeagerEntities DbContext = new BillYeagerEntities()) 
       { 
        DbContext.Database.Connection.Open(); 

        var restaurants = await DbContext.Restaurants.GroupBy(g => g).Select(s => 
         new RestaurantList() 
         { 
          Name = s.Key.Name, 
          City = s.Key.City, 
          Phone = s.Key.Phone, 
          AvgRating = s.Average(a => Convert.ToDecimal(a.Rating.RatingValue)), 
          NbrOfPeopleRating = s.Distinct().Count(c => Convert.ToBoolean(c.RatingId)), 
          Id = s.Key.Id 
         }).ToListAsync(); 

        return restaurants; 
       } 
      } 
      catch (Exception) 
      { 
       throw; 
      } 
     } 
    } 
} 

更新,我需要做我的EDMX文件

<edmx:ConceptualModels> 
     <Schema Namespace="BillYeagerModel" Alias="Self" annotation:UseStrongSpatialTypes="false" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm"> 
     <Function Name="ParseDecimal" ReturnType="Edm.Decimal"> 
      <Parameter Name="bytevalue" Type="Edm.Byte" /> 
      <DefiningExpression> 
       cast(bytevalue as Edm.Decimal) 
      </DefiningExpression> 
     </Function> 

C#擴展方法,這是對我的項目的根類 - 不在我的EDMX裏面

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Data.Entity; 

namespace BillYeagerDB 
{ 
    public partial class EdmxExtensionMethods : DbContext 
    { 
     [DbFunctionAttribute("BillYeagerDB", "ParseDecimal")] 
     public static Decimal ParseDecimal(byte bytevalue) 
     { 
      return Convert.ToDecimal(bytevalue); 
     } 
    } 
} 

更新Linq查詢 - 請注意,沒有設計時編譯錯誤和項目成功編譯

namespace BillYeagerDB 
{ 
    public class BillYeagerDB 
    { 
     public async Task<List<RestaurantList>> GetRestaurantListAsync() 
     { 
      try 
      { 
       using (BillYeagerEntities DbContext = new BillYeagerEntities()) 
       { 
        DbContext.Database.Connection.Open(); 

        var restaurants = await DbContext.Restaurants.GroupBy(g => g).Select(s => 
         new RestaurantList() 
         { 
          Name = s.Key.Name, 
          City = s.Key.City, 
          Phone = s.Key.Phone, 
          AvgRating = s.Average(a => EdmxExtensionMethods.ConvertToDecimal(a.Rating.RatingValue)), 
          NbrOfPeopleRating = s.Distinct().Count(c => Convert.ToBoolean(c.RatingId)), 
          Id = s.Key.Id 
         }).ToListAsync(); 

        return restaurants; 
       } 
      } 
      catch (Exception) 
      { 
       throw; 
      } 
     } 
    } 
} 
+0

你應該能夠將您的字節直接在查詢轉換爲不同的類型,而無需使用一種自定義方法。也許不是直接加倍(我不確定),但如果不是,中間轉換應該可以工作,也許字節 - > int - > double。 – hvd

+0

你自己的解決方案也適用於我;你應該將它作爲答案發布並接受它,以便我們可以投票! –

回答

-1

嘗試重寫你的選擇方法是:

var restaurants = await DbContext.Restaurants.GroupBy(g => g).ToListAsync(); 
return restaurants.Select(s => 
    new RestaurantList() 
    { 
    Name = s.Key.Name, 
    City = s.Key.City, 
    Phone = s.Key.Phone, 
    AvgRating = s.Average(a => Convert.ToDecimal(a.Rating.RatingValue)), 
    NbrOfPeopleRating = s.Distinct().Count(c => Convert.ToBoolean(c.RatingId)), 
    Id = s.Key.Id 
    }); 
+0

-1,因爲這會強制檢索不感興趣的數據,並且會在禁用延遲加載時引發異常。 – hvd

+0

在這種情況下,將從DB中獲取什麼樣的無趣數據?還有什麼其他的方法可以避免EF限制調用「未被分離」的.NET方法? LINQ2SQL? –

+1

未投影的所有餐廳數據仍將被檢索。單獨的查詢將被用於爲每個餐廳檢索「a.Rating」(或者如果任何餐館沒有評分,或者如果延遲加載被禁用則被提及的例外)。至於另一種方式,請參閱我對這個問題的評論。 – hvd

1

我知道我是一個有點晚到黨但任何人做一個谷歌搜索:

我有這個問題,事實證明,類的DbFunctionAttribute必須有sa我命名空間作爲edmx模式。

因此,在這種情況下,無論是EDMX架構命名空間更改爲BillYeagerDB,
或更改EdmxExtensionMethods命名空間BillYeagerModel

相關問題