0

更新示例以显示更一般的用法。

我有一个实体允许用户提供本地化:

public class ResourceValue
{
    public int ResourceValueId { get; set; }
    public string EnglishValue { get; set; }
    public string FrenchValue { get; set; }
    public string SpanishValue { get; set; }
    etc...
}

用于许多其他实体,如下所示:

public class SomeEntity
{
    public int Id { get; set; }
    public virtual ResourceValue Name { get; set; }
    public virtual ResourceValue ShortDescription { get; set; }
    public virtual ResourceValue LongDescription { get; set; }
    etc...
}

我想做这样的事情:

return context.SomeEntities.OrderBy(x => x.Name);

并像我这样做一样进行这项工作:

return context.SomeEntities.OrderBy(x => x.Name.FrenchValue);

基于 CurrentUICulture 是“fr-CA”。

我一直在根据 Marc Gravell 的回答尝试一些事情:https ://stackoverflow.com/a/1231941但一直无法得到我想要的。

更新 - 这非常接近,但我宁愿将其命名为“OrderBy”,以便最终编码器无需特别考虑即可使用它:

    public static IOrderedQueryable<TSource> OrderBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector)
    {
        return ApplyLocalizedOrder(source, keySelector, "OrderBy");
    }

    public static IOrderedQueryable<TSource> ApplyLocalizedOrder<TSource, TKey>(IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, string methodName)
    {
        ParameterExpression arg = keySelector.Parameters[0];
        Expression expr = Expression.PropertyOrField(keySelector.Body, GetCurrentCulture());
        LambdaExpression lambda = Expression.Lambda<Func<TSource, string>>(expr, arg);

        return (IOrderedQueryable<TSource>)typeof(Queryable).GetMethods().Single(
                method => method.Name == methodName
                        && method.IsGenericMethodDefinition
                        && method.GetGenericArguments().Length == 2
                        && method.GetParameters().Length == 2)
                .MakeGenericMethod(typeof(TSource), expr.Type)
                .Invoke(null, new object[] { source, lambda });
    }
4

2 回答 2

0

虽然动态创建 lambda 表达式很酷,但您可以通过创建一个在查询之上应用排序的方法以更简单的方式获得结果。该方法看起来像这样:

    private static IQueryable<SomeEntity> OrderByName(IQueryable<SomeEntity> source, string culture)
    {
        if (culture == "fr-CA")
        {
            return source.OrderBy(x => x.Name.FrenchValue);
        }

        return source.OrderBy(x => x.Name.EnglishValue);
    }

然后你就可以按如下方式使用它:

OrderByName(context.SomeEntities, "en-US")

这是整个示例:

public class MyCtx1 : DbContext
{
    public DbSet<SomeEntity> SomeEntities { get; set; }
    public DbSet<ResourceValue> ResourceValues { get; set; }
}

public class SomeEntity
{
    public int Id { get; set; }
    public virtual ResourceValue Name { get; set; }
}

public class ResourceValue
{
    public int ResourceValueId { get; set; }
    public string EnglishValue { get; set; }
    public string FrenchValue { get; set; }
}

class Program
{

    private static IQueryable<SomeEntity> OrderByName(IQueryable<SomeEntity> source, string culture)
    {
        if (culture == "fr-CA")
        {
            return source.OrderBy(x => x.Name.FrenchValue);
        }

        return source.OrderBy(x => x.Name.EnglishValue);
    }

    static void Main(string[] args)
    {
        using (var context = new MyCtx1())
        {
            if (!context.SomeEntities.Any())
            {
                context.SomeEntities.Add(
                    new SomeEntity() 
                    { 
                        Name = new ResourceValue()
                        {
                            EnglishValue = "abc - en",
                            FrenchValue = "xyz - fr"
                        }
                    });

                context.SomeEntities.Add(
                    new SomeEntity() 
                    { 
                        Name = new ResourceValue()
                        {
                            EnglishValue = "xyz - en",
                            FrenchValue = "abc - fr"
                        }
                    });

                context.SaveChanges();
            }

            Console.WriteLine("Ordered by english name");
            DisplayResults(OrderByName(context.SomeEntities, "en-US"));

            Console.WriteLine("Ordered by french name");
            DisplayResults(OrderByName(context.SomeEntities, "fr-CA"));
        }
    }

    private static void DisplayResults(IQueryable<SomeEntity> q)
    {
        foreach (var e in q)
        {
            Console.WriteLine(e.Id);
        }                
    }

结果:

Ordered by english name
1
2
Ordered by french name
2
1
Press any key to continue . . .
于 2012-09-19T19:54:23.293 回答
0
context.SomeEntities.Select(v => v.Name.FrenchName).OrderBy(x => x);

但甚至比您get的名字更好,返回当前文化或某种文化或您的代码要求的任何内容,当您的班级可以做到时,没有理由在 Linq 查询中这样做。当它在课堂上完成时,无论如何都会更好,因为无论你在哪里调用代码,它都会返回正确的文化。

于 2013-01-09T03:19:00.817 回答