LINQ to Entities不能识别“Double Parse(System.String)”方法,并且此方法不能被转换为存储expression式

当我尝试运行报告时出现错误。 问题是: model.Referring = Math.Round(_newSurveyResult.Select(m => string.IsNullOrEmpty(m.Question1) ? 0 : Double.Parse(m.Question1)).Average());

 public class SummaryDetails { public int ChannelId { get; set; } public int ChannelGroupId { get; set; } public string Question1 { get; set; } public string Question2 { get; set; } public string Question3 { get; set; } public string Question4 { get; set; } public int OrganizationId { get; set; } } public ActionResult AreaManager(AreaManagerModel model) { model.ShowCustomerReport = false; model.ShowSurveyReport = true; LoadModelVariablesonPostBack(model, 8); var _newSurveyResult = ( from ls in SessionHandler.CurrentContext.LennoxSurveyResponses join ml in SessionHandler.CurrentContext.MailingListEntries on ls.SurveyCode equals ml.SurveyCode join m in SessionHandler.CurrentContext.MailingLists on ml.MailingListId equals m.MailingListId join ch in SessionHandler.CurrentContext.Channels on m.ChannelId equals ch.ChannelId join cg in SessionHandler.CurrentContext.ChannelGroups on ch.ChannelGroupId equals cg.ChannelGroupId join dcg in SessionHandler.CurrentContext.ChannelGroups on cg.ParentChannelGroupId equals dcg.ChannelGroupId join ncg in SessionHandler.CurrentContext.ChannelGroups on dcg.ParentChannelGroupId equals ncg.ChannelGroupId join pcg in SessionHandler.CurrentContext.ChannelGroups on ncg.ParentChannelGroupId equals pcg.ChannelGroupId select new SummaryDetails { OrganizationId = ch.OrganizationId, Question1 = ls.Question1Answer, Question2 = ls.Question2Answer, Question3 = ls.Question3Answer, Question4 = ls.Question4Answer, ChannelId = ch.ChannelId, ChannelGroupId = model.TMId != 0 ? cg.ChannelGroupId : model.DistrictId != 0 ? dcg.ChannelGroupId : model.AreaId != 0 ? ncg.ChannelGroupId : model.NationId != 0 ? pcg.ChannelGroupId : model.AreaId == 0 ? ncg.ChannelGroupId : model.DistrictId == 0 ? dcg.ChannelGroupId : cg.ChannelGroupId } ); var _newSentSurveys = ( from ml in SessionHandler.CurrentContext.MailingListEntries join m in SessionHandler.CurrentContext.MailingLists on ml.MailingListId equals m.MailingListId join ch in SessionHandler.CurrentContext.Channels on m.ChannelId equals ch.ChannelId join cg in SessionHandler.CurrentContext.ChannelGroups on ch.ChannelGroupId equals cg.ChannelGroupId join dcg in SessionHandler.CurrentContext.ChannelGroups on cg.ParentChannelGroupId equals dcg.ChannelGroupId join ncg in SessionHandler.CurrentContext.ChannelGroups on dcg.ParentChannelGroupId equals ncg.ChannelGroupId join pcg in SessionHandler.CurrentContext.ChannelGroups on ncg.ParentChannelGroupId equals pcg.ChannelGroupId where (ml.EmailDate != null || ml.LetterDate != null || ml.EmailBounce == null) select new SummaryDetails { OrganizationId = ch.OrganizationId, ChannelId = ch.ChannelId, ChannelGroupId = model.TMId != 0 ? cg.ChannelGroupId : model.DistrictId != 0 ? dcg.ChannelGroupId : model.AreaId != 0 ? ncg.ChannelGroupId : model.NationId != 0 ? pcg.ChannelGroupId : model.AreaId == 0 ? ncg.ChannelGroupId : model.DistrictId == 0 ? dcg.ChannelGroupId : cg.ChannelGroupId } ); if (model.ChannelId != 0) { _newSurveyResult = _newSurveyResult.Where(p => p.ChannelId == model.ChannelId); _newSentSurveys = _newSentSurveys.Where(p => p.ChannelId == model.ChannelId); } else if (model.TMId != 0) { _newSurveyResult = _newSurveyResult.Where(p => p.ChannelGroupId == model.TMId); _newSentSurveys = _newSentSurveys.Where(p => p.ChannelGroupId == model.TMId); } else if (model.DistrictId != 0) { _newSurveyResult = _newSurveyResult.Where(p => p.ChannelGroupId == model.DistrictId); _newSentSurveys = _newSentSurveys.Where(p => p.ChannelGroupId == model.DistrictId); } else if (model.AreaId != 0) { _newSurveyResult = _newSurveyResult.Where(p => p.ChannelGroupId == model.AreaId); _newSentSurveys = _newSentSurveys.Where(p => p.ChannelGroupId == model.AreaId); } else if (model.NationId != 0) { _newSurveyResult = _newSurveyResult.Where(p => p.ChannelGroupId == model.NationId); _newSentSurveys = _newSentSurveys.Where(p => p.ChannelGroupId == model.NationId); } else if (model.NationId == 0) { _newSurveyResult = _newSurveyResult.Where(p => p.OrganizationId == 8); _newSentSurveys = _newSentSurveys.Where(p => p.OrganizationId == 8); } else if (model.AreaId == 0) { _newSurveyResult = _newSurveyResult.Where(p => p.ChannelGroupId == model.LoggedChannelGroupId); _newSentSurveys = _newSentSurveys.Where(p => p.ChannelGroupId == model.LoggedChannelGroupId); } else if (model.DistrictId == 0) { _newSurveyResult = _newSurveyResult.Where(p => p.ChannelGroupId == model.LoggedChannelGroupId); _newSentSurveys = _newSentSurveys.Where(p => p.ChannelGroupId == model.LoggedChannelGroupId); } else if (model.TMId == 0) { _newSurveyResult = _newSurveyResult.Where(p => p.ChannelGroupId == model.LoggedChannelGroupId); _newSentSurveys = _newSentSurveys.Where(p => p.ChannelGroupId == model.LoggedChannelGroupId); } model.SentSurveys = _newSentSurveys.Count() > 0 ? _newSentSurveys.Count() : 0; model.CompletedSurveys = _newSurveyResult.Count() > 0 ? _newSurveyResult.Count() : 0; model.PercentageComplete = model.SentSurveys != 0 ? (Convert.ToDouble(model.CompletedSurveys) / Convert.ToDouble(model.SentSurveys)) : 0; if (_newSurveyResult.Count() > 0) { model.Referring = Math.Round(_newSurveyResult.Select(m => string.IsNullOrEmpty(m.Question1) ? 0 : Double.Parse(m.Question1)).Average()); model.ServicePerformance = Math.Round(_newSurveyResult.Select(m => string.IsNullOrEmpty(m.Question2) ? 0 : Double.Parse(m.Question2)).Average()); model.InstallPerformance = Math.Round(_newSurveyResult.Select(m => string.IsNullOrEmpty(m.Question3) ? 0 : Double.Parse(m.Question3)).Average()); model.ReferringLennox = Math.Round(_newSurveyResult.Select(m => string.IsNullOrEmpty(m.Question4) ? 0 : Double.Parse(m.Question4)).Average()); double overAllScore = CalculateOverallScore( _newSurveyResult.Select(m => string.IsNullOrEmpty(m.Question1) ? 0 : Double.Parse(m.Question1)).Sum(), _newSurveyResult.Select(m => string.IsNullOrEmpty(m.Question2) ? 0 : Double.Parse(m.Question2)).Sum(), _newSurveyResult.Select(m => string.IsNullOrEmpty(m.Question3) ? 0 : Double.Parse(m.Question3)).Sum(), _newSurveyResult.Select(m => string.IsNullOrEmpty(m.Question4) ? 0 : Double.Parse(m.Question4)).Sum(), _newSurveyResult.Count()); model.OverallScore = Math.Round(overAllScore); } } 

这里的问题是您的查询正在被翻译成SQL并在数据库上运行,entity framework不知道如何将Double.Parse转换为有效的SQL代码。 但是,您可以定义一个自定义方法来执行parsing,并告诉entity framework如何将该方法转换为SQL。 这是怎么回事:

定义翻译

在文本编辑器中打开* .edmx文件,然后查找<edmx:ConceptualModels>标签。 在那之下你应该看到一个<Schema Namespace="YourModel" ...>标签。 在Schema标签内,添加以下内容:

  <Function Name="ParseDouble" ReturnType="Edm.Double"> <Parameter Name="stringvalue" Type="Edm.String" /> <DefiningExpression> cast(stringvalue as Edm.Double) </DefiningExpression> </Function> 

这定义了您的自定义ParseDouble函数将被转换成的Enity-SQL代码。

创build一个要翻译的方法

现在我们需要在代码中定义一个可以放在LINQ语句中的匹配函数。 您的EDMX文件用于生成从ObjectContextinheritance的部分类。 由于它是一个部分类,你可以添加你自己的方法,而不用触及生成的代码 – 只要确保类名匹配。

 using System.Data.Objects.DataClasses; public partial class YourObjectContext { /// <summary> /// This method exists for use in LINQ queries, /// as a stub that will be converted to a SQL CAST statement. /// </summary> [EdmFunction("YourModel", "ParseDouble")] public static double ParseDouble(string stringvalue) { return Double.Parse(stringvalue); } } 

现在,您可以返回到LINQ语句,并用Double.ParsereplaceDouble.Parse任何实例。 由于这是一个实际调用Double.Parse的实际方法,它将在LINQ to Objects调用上工作,并且由于它也在EDMX文件中定义,所以它也可以通过LINQ to Entities转换为SQL。

但是等等,你还没有完成!

我注意到你的LINQ语句也包含对Math.Round的调用。 我不知道如果Entity Framework包含该方法的翻译,但如果没有,那么在修复Double.Parse之后,您将得到与该方法相同的错误。 幸运的是,这种情况下的解决scheme几乎完全一样,只是在EDMX文件中定义的函数看起来像这样:

  <Function Name="Round" ReturnType="Edm.Double"> <Parameter Name="input" Type="Edm.Double" /> <DefiningExpression> Round(input) </DefiningExpression> </Function> 

您可以使用这个EDM规范函数列表来查看<DefiningExpression>标签中的有效内容。