使用antor列表中的数组的动态列表

时间:2019-06-14 20:21:20

标签: entity-framework linq

我的应用程序是ASP.NET MVC 5 / SQL Server。

我正在尝试根据数组从列表中选择特定的列:

第一个列表有200列:年龄,性别,.....

select distinct on (customer1.customer_id)
         customer1.customer_id,
         first_name,
         last_name,
         email,
         purchase.purchase_id,
         purchase.purchase_time,
         purchase_item.quantity,
         purchase_item.total_amount_paid
FROM customer1
  LEFT JOIN purchase ON customer1.customer_id = purchase.customer_id
  LEFT JOIN purchase_item ON purchase.purchase_id = purchase_item.purchase_id
ORDER BY customer1.customer_id, purchase_time desc;

第二个列表有20列:年龄,性别,......

从视图中,选择要显示的项目:


 customer_id | first_name | last_name |           email           | purchase_id |         purchase_time         | quantity | total_amount_paid
-------------+------------+-----------+---------------------------+-------------+-------------------------------+----------+-------------------
           1 | James      | Smith     | jamessmith@example.com    |         102 | 2019-06-14 20:17:26.759086+00 |        1 |           1995.00
           2 | Mary       | Johnson   | maryjohnson@example.com   |         103 | 2019-06-14 20:17:26.759098+00 |        2 |            200.00
           3 | John       | Williams  | johnwilliams@example.com  |         104 | 2019-06-14 20:17:26.759109+00 |        1 |             60.00
           4 | Patricia   | Brown     | patriciabrown@example.com |             |                               |          |
           5 | Michael    | Garcia    | michaelgarcia@example.com |         105 | 2019-06-14 20:17:26.75912+00  |        1 |            400.00
(5 rows)

我得到enter image description here

为了获得这两个特定的列,我尝试了

var list1 = _reportRepository.ShowMasteView().ToList(); 

我遇到错误

  

无法解析符号“包含”

我可以使用以下方法完成

string[] lits2 = showColumn.Where(c => c.Value == true).Select(c=> c.Key).ToArray();

linq中还有更好的方法吗?

3 个答案:

答案 0 :(得分:1)

据我了解,您似乎正在尝试提取/选择仅具有所需属性/列的动态对象。

这可以通过构建动态表达式/函数以应用于Select

来实现

以下内容基于模型类型和提供的属性来构建表达式

static class DynamicExtensions {
    public static IQueryable<dynamic> SelectDynamic<TModel>(this IQueryable<TModel> query, ISet<string> propertyNames) {
        var selector = query.BuildSelectorFor(propertyNames);
        return query.Select(selector);
    }

    static Expression<Func<TModel, dynamic>> BuildSelectorFor<TModel>(this IQueryable<TModel> query, ISet<string> propertyNames) {
        var modelType = typeof(TModel);
        var properties = modelType.GetProperties().Where(p => propertyNames.Contains(p.Name));

        // Manually build the expression tree for 
        // the lambda expression v => new { PropertyName = v.PropertyName, ... }

        // (TModel v) =>
        var parameter = Expression.Parameter(modelType, "v");
        // v.PropertyName
        var members = properties.Select(p => Expression.PropertyOrField(parameter, p.Name));
        var addMethod = typeof(IDictionary<string, object>).GetMethod(
                    "Add", new Type[] { typeof(string), typeof(object) });
        // { { "PropertyName", v.PropertyName}, ... }
        var elementInits = members.Select(m =>
            Expression.ElementInit(addMethod, Expression.Constant(m.Member.Name), Expression.Convert(m, typeof(object))));
        // new ExpandoObject()
        var newExpando = Expression.New(typeof(ExpandoObject));
        // new ExpandoObject() { { "PropertyName", v.PropertyName}, ... }
        var expando = Expression.ListInit(newExpando, elementInits);
        // (TModel v) => new ExpandoObject() { { "PropertyName", v.PropertyName}, ... }
        var lambdaExpression = Expression.Lambda<Func<TModel, dynamic>>(expando, parameter);
        return lambdaExpression;
    }
}

这利用了ExpandoObject的优势,该成员的成员可以在运行时动态添加和删除。

下面的测试是如何调用上述函数的示例。

[TestMethod]
public void DynamicList() {
    var list1 = new List<Person>
    {
        new Person{ Gender = "Male", Age = 10, FirstName = "Nama1", SampleNumber = 12},
        new Person{ Gender = "Male", Age = 12, FirstName = "Nama2", SampleNumber = 13},
        new Person{ Gender = "Female", Age = 13, FirstName = "Nama3", SampleNumber = 14},
        new Person{ Gender = "Male", Age = 14, FirstName = "Nama4", SampleNumber = 15},
    };
    var keys = new string[] { "Age", "Gender", };

    var nList = list1.AsQueryable().SelectDynamic(new HashSet<string>(keys));

    foreach (IDictionary<string, object> row in nList) {
        var msg = $"{{ {keys[0]} = {row[keys[0]]}, {keys[1]} = {row[keys[1]]} }}";
        Debug.WriteLine(msg);
    }
}

并产生以下输出

{ Age = 10, Gender = Male }
{ Age = 12, Gender = Male }
{ Age = 13, Gender = Female }
{ Age = 14, Gender = Male }

动态对象可以在视图中使用,只需调用所需成员即可。

例如,假设您有一个如下模型

public class MyViewModel {
    public string MyProperty { get; set; }
    public string[] Keys  { get; set; }
    public List<dynamic> MyDynamicProperty { get; set; }
}

已填充数据并提供给视图的

var list1 = _reportRepository.ShowMasteView(); 
var keys = new string[] { "Age", "Gender", };
var nList = list1.AsQueryable().SelectDynamic(new HashSet<string>(keys));

var viewModel = new MyViewModel {
    MyProperty = "Hello World",
    MyDynamicProperty = nList.ToList(),
    Keys = keys
};

return View(viewModel);

然后在视图中可以根据需要使用模型,进行强制转换以访问expando对象中的成员。

@model MyViewModel

...

<h2>@Model.MyProperty</h2>
<table>
    <tr>
@foreach(string key in Model.Keys) {
      <th>@key</th>
}
    </tr>
@foreach (IDictionary<string, object> row in Model.MyDynamicProperty) {
    <tr>
    @foreach(string key in Model.Keys) {
      <td>@row[@key]</td>
    }
    </tr>
}
</table>

答案 1 :(得分:0)

我认为您只需要在列表2上使用“包含”即可。

var nList = list1.Where(t => lits2.Contains(t1));

包含是用于列表的方法。您曾经尝试在字符串上使用它的代码。

答案 2 :(得分:0)

如果您有一个班级的两个清单

public class Person
{
    public int id { get; set; }
    public string name { get; set; }
}

如果列表如下:

  var list1 = new List<Person>
       {
           new Person{ id = 1, name = "Nama1"},
           new Person{ id = 2, name = "Nama2"},
           new Person{ id = 3, name = "Nama3"},
           new Person{ id = 4, name = "Nama4"},
       };

        var list2 = new List<Person>
        {
            new Person{ id = 1, name = "Nama1"},
            new Person{ id = 2, name = "Nama2"},
        };

您可以通过以下方式进行过滤

        var keys = list2.Select(x => x.id).ToList();

        var filter1= list1.Where(x => keys.Contains(x.id)).ToList();
        var filter2= list1.Where(x => keys.Contains(x.id)).Select(x => new { x.name }).ToList();
        var filter3= list1.Select(x => new
        {
            id = x.id,
            name = x.name,
            check = keys.Contains(x.id)
        }).Where(x => x.check).ToList();

如果您有字符串数组 您可以使用以下代码

相同的数组字符串

var lis1 = new string[] {"name1", "name2","name3" };
var lis2 = new string[] { "name1" };

您可以通过以下方式过滤字符串数组

 var items1= lis1.Where(x=>lis2.Contains(x)).ToList();
 var items= lis1.Select(x=> new { x, check= lis2.Contains(x) }).Where(x=>x.check == true).ToList();