Динамический список с использованием массива из списка anthor - PullRequest
1 голос
/ 14 июня 2019

Мое приложение - ASP.NET MVC 5 / SQL Server.

Я пытаюсь выбрать определенные столбцы из списка на основе массива:

Первый список содержит 200 столбцов: возраст, пол, .....

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

Второй список состоит из 20 столбцов: возраст, пол, ......

В представлении я выбираю элементы для отображения:

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

Я получаю enter image description here

Чтобы получить эти два конкретных столбца, я попытался

 var nList = list1.Select(t2 => lits2.Any(t1 => t2.Contains(t1)));

Я получаю ошибку

Не удается разрешить символ "Содержит"

Я смог сделать это с помощью следующего

var keys = "Age,Gender";
var connection = 
ConfigurationManager.ConnectionStrings["DALEntities"].ConnectionString;
            using (var dataAdapter = new SqlDataAdapter("SELECT " + keys
             + " from dbo.vw_MasterView", connection))
            {
                var dataTable = new DataTable();

                dataAdapter.Fill(dataTable);
                dataAdapter.FillSchema(dataTable, SchemaType.Mapped);
                return dataTable;
            }

Есть ли лучший способ в linq?

Ответы [ 3 ]

1 голос
/ 17 июня 2019

Насколько я понимаю, кажется, что вы пытаетесь извлечь / выбрать динамический объект, который имеет только нужные свойства / столбцы.

Это может быть достигнуто путем создания динамического выражения / функции для применения к 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>
0 голосов
/ 16 июня 2019

Если у вас есть два списка класса человека

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();
0 голосов
/ 14 июня 2019

Я думаю, вам просто нужно использовать Contains в вашем списке2.

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

Содержит метод для списков. Код, который вы пытались использовать в строке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...