无法翻译成LINQ to Entities存储表达式

时间:2013-11-25 00:12:14

标签: c# .net asp.net-mvc entity-framework linq-to-entities

我对LINQ to Entities相对较新,但是很多时候使用LINQ to Sql。

我正在使用带有EntityFramework 6和MVC 5的Visual Studio 2013。

两者之间最大的区别是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 定义为类型字节。

如果有人能够理顺我,我会非常感激。

这是我的代码。我正在尝试使用以下查询,由于转换问题,我知道这些查询无效(如前所述)。

原始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;
            }
        }
    }
}

2 个答案:

答案 0 :(得分:2)

我知道我参加派对的时间有点晚,但对于那些正在进行Google搜索的人来说:

我遇到了这个问题,事实证明DbFunctionAttribute所在的类必须具有与edmx架构相同的命名空间。

因此,在这种情况下,将edmx架构命名空间更改为BillYeagerDB,
或将EdmxExtensionMethods名称空间更改为BillYeagerModel

答案 1 :(得分:-1)

尝试将select方法重写为:

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
  });