实体框架-LINQ-动态列名

时间:2018-10-11 10:17:44

标签: c# linq lambda entity-framework-6

我知道这个问题被问过几次,但是我遇到的答案越多,我就越困惑。

鉴于我有一个表Categories,并且在此表列中:Category1Category2Category3等等。如何编写下面和下面的方法使用参数(在这种情况下为catno

尽可能简化;

public List<string> GetProductCategories(int catno)
{
    using (var ctx = new myEntities())
    {
        return (from c in ctx.Categories
                select c.Category1).ToList();
               //1 being the catno parameter obviously
    }
}

我绝对不要要使用Dynamic Linq库,因为它的类型不安全。尽管(显然)一个有效的答案会很好,但是提供了对该问题和解决方案的详细说明。

预先感谢

3 个答案:

答案 0 :(得分:0)

public List<string> GetProductCategories(int catno)
{
    string catName = string.Format("Category{0}", catno);
    using (var ctx = new myEntities())
    {
        var result = ctx.Categories.Select(x => {
                var prop = x.GetType().GetProperty(catName);
                if (prop == null)
                {
                    return double.NaN;
                }
                return double.Parse(prop.GetValue(x).ToString());
            }).ToList();
        return result.Where(x => !double.IsNaN(x)).ToList();
    }
}

答案 1 :(得分:0)

如果您想要完全的类型安全性,除了使用开关大小写将整数映射到其对应的类别外,我没有其他方法:

public List<string> GetProductCategories(int catno)
{
    using (var ctx = new myEntities())
    {
        switch (catno)
        {
            case 1:
                return ctx.Categories.Select(c => c.Category1).ToList();
            case 2:
                return ctx.Categories.Select(c => c.Category2).ToList();
            default:
                throw new ArgumentException("Category number not supported!");
        }
    }
}

您显然可以做的另一件事是重构代码,以便获得包含字符串属性以及数字的Category类的列表,然后您可以编写如下内容:

return ctx.Categories.Where(c => c.CategoryNumber == catno)
    .Select(c => c.CategoryDescription)
    .ToList();

我认为您应该重构代码。看到“ Category1”和“ Category2”时,我闻到不好的设计,听起来这些应该是“类别”列表中的项目。

还对Dynamic Linq进行了评论,例如,如果您收到来自无法控制的客户端的请求,则使用Dynamic linq并没有错。如果找不到该属性,则可以简单地返回一个错误。

答案 2 :(得分:0)

您可以定义基于字符串名称选择属性的表达式。然后,在IQueryable界面中,可以在Select参数中使用它。不过,您将需要使用方法语法:

public List<string> GetProductCategories(int catno)
{
    var parameter = Expression.Parameter(typeof(Category));
    var property = Expression.Property(parameter, $"Category{catno}");
    var selector = Expression.Lambda<Func<Category, string>>(property, parameter);

    using (var ctx = new myEntities())
    {
        return ctx.Categories
            .Select(selector)
            .ToList();
    }
}

Expression.Property方法正在执行一些类型检查,因此,如果在类型Category上未定义给定属性,它将抛出异常。例如,如果没有Category0属性,则此操作将失败:

var property = Expression.Property(parameter, "Category0");