2013-11-25 32 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

相关问题