【问题标题】:Sort entities based on a substring根据子字符串对实体进行排序
【发布时间】:2013-09-19 10:08:03
【问题描述】:

我正在使用带有 Code First 的 EntityFramework 5。

请看下面的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(如果没有其他方法我也可以使用产品列表)。

谢谢大家!

【问题讨论】:

  • 您不能直接在 Linq2Entity 中使用您的 .NET 方法。可以分享GetLocalizedName的代码吗?
  • 老实说,我认为这是绕过本地化的错误方法。我认为您应该有一个翻译表,其中包含prodScrewDriver,以及各种文化的映射。然后,您的 Name 方法仅返回 prodScrewDriver 并且接口会对其进行适当的翻译。
  • 产品名称始终包含所有可用语言?
  • 谢谢大家。是的,当然,使用单独的语言表是正常的做法。但在这种情况下,我没有这个选项。这就是为什么我必须想出这个多语言字符串。没想到你会比我的查询问题更关心这个;-)

标签: c# linq entity-framework


【解决方案1】:

结果必须是 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 } 表。

【讨论】:

  • 谢谢 Henk,这就是我要找的。​​span>
【解决方案2】:

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

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

【讨论】:

  • 如果你指的是这篇文章,是的。那又怎样?
【解决方案3】:

我认为管理一个名字的翻译将是一项非常艰巨的工作。 我会将语言名称拆分为主详细信息:

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

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

【讨论】:

  • 您好 Jeroen,非常感谢您的建议。但就我而言,使用单个多语言字符串实际上使我免于做“地狱般的工作”。但这是由于上下文和太大的故事无法在这里讲述。所以,再次感谢。
猜你喜欢
  • 2015-08-13
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-13
  • 1970-01-01
  • 2021-10-07
相关资源
最近更新 更多