如何根据用户选择返回选定的列

时间:2017-11-28 18:22:49

标签: asp.net-mvc entity-framework asp.net-web-api lambda

我正在尝试根据名为字段的参数来限制API返回哪些字段,我接受多个字符串执行此操作

private readonly string [] fields;

public string[] SelectiveSerializer(string fields)
{
    string[] _fields;
    var fieldColl = fields.Split(',');
    _fields = fieldColl
        .Select(f => f.ToLower().Trim())
        .ToArray();
    return _fields;

}

我希望能够根据用户在_fields中给出的任何内容来选择我返回的内容。正常的方式:

 var linq = (from entity in db.users
             where entity.ID== id
              && entity.ON== false
             select( new {
             ID = entity.ID,
             FirstName = entity.FirstName,
             LastName =entity.LastName,
             FotherName = entity.FotherName
             }).ToList();

但是在这里我必须指定Select(ID,FirstName ..etc)中的字段,我希望它基于[]具有的字段是动态的。有没有办法做到这一点?

这种(这是错误的):

var linq = (from entity in db.users
             where entity.ID== id
              && entity.ON== false
             select( new {
             foreach (string s in _fields)
             {
                    entity.s;
             }
             }).ToList();

2 个答案:

答案 0 :(得分:0)

为每个作业使用三元表达式

var user = entityContext.Users.Where(u => u.ID == id)
    .Select(u => new {
        ID =  _fields.Contains['id'] ? u.ID : 0,
        FirstName = _fields.Contains['firstname'] ? u.FirstName : null,
        LastName = _fields.Contains['lastname'] ? u.LastName : null,
        otherName = _fields.Contains['othername'] ? u.otherName : null
    })
    .ToList();

我还会将字段名称放在HashSet<string>中以获得更好的效果。

var _fields = new HashSet<string>(fields.Split(',').Select(f => f.ToLower().Trim()));

此解决方案保留所有属性,但将不需要的属性设置为null。如果您想动态添加属性,请参阅另一个SO问题:How to dynamically create a class in C#?。但请注意,这仅适用于动态处理此类对象的情况。

答案 1 :(得分:0)

我终于能够用最少的工作来做到这一点。 假设过滤器是一个字符串列表。字符串数组。

为了避免反射和所有爵士乐,我迭代每条记录并查看变量是否在过滤器列表中,然后创建一个带有(var,val)的dic条目,假设同一记录中没有重复的var,可以抓住,如果你想,但我没有这个问题。 然后在最后将该dic添加到列表中。 该方法接受匿名类型列表和筛选器列表。

public static List<Dictionary<string, object>> filteredList(IEnumerable source, string[] filter)
    {
        var filteredList = new List<Dictionary<string, object>>();
        foreach (var single in source)
        {
            var type = single.GetType();
            var props = type.GetProperties();
            var singleRecord = new Dictionary<string, object>();
            foreach (var v in props)
            {
                if (filter.Contains(v.Name))
                {
                    var tempValue = type.GetProperty(v.Name).GetValue(single, null);
                    singleRecord.Add(v.Name, tempValue);
                }

            }
            filteredList.Add(singleRecord);
        }
        return filteredList;
    }