代码之家  ›  专栏  ›  技术社区  ›  Pierrick Martellière

asp.net-LINQ to Entities无法识别方法“Char get_Chars(Int32)”方法,并且此方法无法转换为存储表达式

  •  -1
  • Pierrick Martellière  · 技术社区  · 8 年前

    我对ASP.NET MVC4和实体框架很陌生。

    我在我的API中设置了一个新方法 partners 有一个 prestation 在GET参数中找到一个名称 预应力 .

    我在标题中发现了错误,不知道该如何修复:

    LINQ to Entities无法识别方法“Char get_Chars(Int32)”方法,并且此方法无法转换为存储表达式。

    我的方法是:

    // GET: api/Partenaires_prestations
    [Authorize]
    [Route("api/Partenaires_prestations")]
    public List<PartenaireMapItem> GetPartenairesWithPrestations()
    {
        Random rnd = new Random();
    
        var queryString = Request.GetQueryNameValuePairs();
    
        var prestation = queryString.FirstOrDefault();
    
        return db.Partenaires
            .Where(p => p.PartenairePrestations.Any(pp => pp.Prestation.NomPrestation == prestation.Value))
            .Select(p => new PartenaireMapItem
            {
                IdPartenaire = p.IdPartenaire,
                FirstName = p.FirstName,
                LastName = p.LastName,
                NomComplet = p.LastName.ToUpper()[0] + ". " + p.FirstName,
                Type = p.Type,
                DureeMin = rnd.Next(2, 50),
                Lat = p.Lat,
                Lng = p.Lng,
                ImageUrl = p.ImageUrl,
                SeDeplace = p.SeDeplace,
                ADomicile = p.ADomicile,
    
                NoteGlobale = rnd.Next(1, 6),
                Prestations = new List<string>(p.PartenairePrestations.Select(y => y.Prestation.NomPrestation))
            }).ToList();
    }
    

    任何帮助都将不胜感激。

    感谢所有愿意花时间阅读/回答这篇文章的人。

    1 回复  |  直到 8 年前
        1
  •  1
  •   Kevin L.    8 年前

    当使用实体框架编写LINQ查询时,它会尝试将查询转换为SQL查询。某些.NET操作无法转换为SQL。我认为冒犯的是:

    p.LastName.ToUpper()[0]
    

    我还希望对rnd.Next()的调用也会导致错误。

    下面是我将如何处理这种情况:

    1. 在没有违规列的情况下执行查询。以.ToList()结束查询。这将把结果集加载到内存中。
    2. 遍历结果集并添加缺少的列。由于结果集已加载到内存中,因此它不会对.NET操作抛出错误。
        var result = db.Partenaires
            .Where(p => p.PartenairePrestations.Any(pp => pp.Prestation.NomPrestation == prestation.Value))
            .Select(p => new PartenaireMapItem {
                IdPartenaire = p.IdPartenaire,
                FirstName = p.FirstName,
                LastName = p.LastName,
                Type = p.Type,
                Lat = p.Lat,
                Lng = p.Lng,
                ImageUrl = p.ImageUrl,
                SeDeplace = p.SeDeplace,
                ADomicile = p.ADomicile,
                Prestations = new List(p.PartenairePrestations.Select(y => y.Prestation.NomPrestation))
            }).ToList();
    
        foreach (var row in result) {
            row.NomComplet = row.LastName.ToUpper()[0] + ". " + row.FirstName;
            row.DureeMin = rnd.Next(2, 50);
            row.NoteGlobale = rnd.Next(1, 6);
        }
    
        return result;
    

    第二种方法是在SQL Server中创建一个存储过程。这将消除拆分查询的需要。这是最有效的方法,但也需要做更多的工作,并为您的应用程序添加更多的层。我只建议您在需要大量流量和数据的情况下使用此选项。

    注意:第三种方法是在db.Partenaires之后立即使用.AsEnumerable()或.ToList()来避免错误。例如:

    db.Partenaires.AsEnumerable().Where ... 或 db.Partenaires.ToList().Where ...

    然而,这种方法的危险在于 它将整个表加载到内存中 . 换句话说,SQL查询将等价于 select * from Partenaires . 然后实体框架将不得不执行额外的查询来检索相关表(如partenairempressions)中的数据,并且它将在内存中执行所有其他过滤和操作。这是 最低效率 选择。虽然这种方法短期内会奏效,但随着数据的增长,它将开始成为性能问题,所以我不建议使用它。

    推荐文章