基于子字符串对实体进行排序

时间:2013-09-19 10:08:04

标签: c# linq entity-framework

我正在使用EntityFramework 5和Code First。

请查看以下POCO。

public class Product
{
    [Key]
    public Guid Id { get; set; }

    public string Name {get; set; }  // e.g. en=Screwdriver;de=Schraubenzieher;fr=Tournevis

    /// <summary>
    /// This will always return a valid string.
    /// </summary>
    /// <param name="languageCode"></param>
    /// <returns></returns>
    public string GetLocalizedName(string languageCode)
    {
        ...
    }
}

如您所见,每个产品都有一个“多语言”名称,其中包含此一个字符串中的所有不同翻译。

我无法想出用LINQ按特定语言对产品进行排序的简单方法。我正在寻找的代码应该是这样的(假设我想要一个基于英文名称的排序集合):

var sortedProducts = from p in Context.Products
                     orderby p.GetLocalizedName("en")
                     select p;

但是,一旦我遍历项目,这将不起作用,例如with .ToList():“LINQ to Entities无法识别方法'System.String GetLocalizedName(System.String)'方法,并且此方法无法转换为商店表达式。”

有没有人对如何解决这个问题有一个很好的想法?结果必须是一个类型为Product的IQueryable(如果没有其他方式我也可以使用产品列表)。

谢谢你们!

3 个答案:

答案 0 :(得分:3)

  

结果必须是类似于Product的IQueryable

那不行。 string GetLocalizedName()是一种C#方法,这就是您收到cannot be translated into a store expression错误的原因。

  

(如果我没有其他方式可以使用产品列表)。

目前,您需要这样做:

  var sortedProducts = from p in Context.Products
                 .ToList()    // switch to IEnumerable and suffer the loss in performance
                 orderby p.GetLocalizedName("en")
                 select p;

备选方案:

  • GetLocalizedName()实现为存储过程并修复映射
  • 重组您的数据模型。添加{ ProductId, LanguageCode, Description }表。

答案 1 :(得分:1)

请注意,订购将在客户端完成。

var sortedProducts = (from p in Context.Products
                 select p)
                 .AsEnumerable()
                 .OrderBy(p => p.GetLocalizedName("en"));

答案 2 :(得分:1)

我认为用一个名字管理翻译,将是一件难以管理的工作。 我会将语言名称拆分为主要细节:

string code = "de";

var sortedProducts = from p in Context.Products
                     join l in Context.ProductNames on p.id equals l.product_id
                     where l.languageCode == code 
                     // you can uncomment the code below to get the english always if the translation in 'code' (german) isn't available, but you need to eliminate duplicates.
                     // || l.languageCode == "en"
                     orderby l.localizedName
                     select new { p.id, p.whatever, l.localizedName };

这样查询就在服务器端执行。 您可以编写查询来查找未翻译的名称。