LINQ to Entities não reconhece o método ‘Double Parse (System.String)’ e esse método não pode ser convertido em uma expressão de armazenamento

Eu recebo o erro quando tento executar o relatório. O problema está aqui: 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); } } 

O problema aqui é que sua consulta está sendo traduzida para SQL e executada no database, e o Entity Framework não sabe como converter Double.Parse em código SQL válido. No entanto, você pode definir um método personalizado para fazer a análise e informar ao Entity Framework como traduzir esse método para SQL. Veja como vai:

Definir a tradução

Abra o arquivo * .edmx em um editor de texto e procure pela tag . Em que você deve ver uma marca . Dentro da tag Schema, adicione o seguinte:

     cast(stringvalue as Edm.Double)   

Isso define o código Enity-SQL para o qual sua function ParseDouble personalizada será traduzida.

Crie um método a ser traduzido

Agora precisamos definir uma function correspondente no código que você pode colocar em sua instrução LINQ. Seu arquivo EDMX é usado para gerar uma class parcial que herda do ObjectContext. Já que é uma class parcial, você pode adicionar seus próprios methods a ela sem tocar no código gerado – apenas certifique-se de que os nomes das classs correspondam.

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

Agora você pode voltar para sua instrução LINQ e replace quaisquer ocorrências de Double.Parse com YourObjectContext.ParseDouble . Como esse é um método real que realmente chama Double.Parse , ele funcionará nas chamadas LINQ to Objects e, como também é definido no arquivo EDMX, também pode ser convertido em SQL pelo LINQ to Entities.

Mas espere, você ainda não terminou!

Percebi que sua instrução LINQ também inclui uma chamada para o Math.Round . Eu não sei de cima da cabeça se o Entity Framework include uma tradução para esse método, mas se não, você obterá o mesmo erro para esse método depois de corrigir o Double.Parse para Double.Parse . Felizmente, a solução para esse caso é quase exatamente a mesma, exceto que a function definida no arquivo EDMX seria algo como isto:

     Round(input)   

Você pode usar essa lista de funções canônicas do EDM para ver o que é válido para colocar dentro das tags .