Как исключить свойство вместо выбора в Lambda LINQ - PullRequest
0 голосов
/ 10 мая 2018

У меня есть код, который выбирает таблицу. Вот мой пример кода:

public IQueryable<MyItem> MyItems(){
    return context.MyItem;
}

Вот пример свойств MyItem

public int Id {get;set;}
public byte[] Image {get;set;}
public string Name {get;set;}

Поскольку byte[] может содержать несколько символов, я не хочу включать их в поиск, поскольку это займет много времени, если у меня будет записи, например, 10000 элементов.

Как правило, я бы Select так:

public IQueryable<MyItem> MyItems(){
    return context.MyItem.Select(item=>new MyItem{
        Id=item.Id,
        Name=item.Name
    });
}

Это нормально для нескольких свойств, но из-за того, что у меня есть 10-20 свойств, было бы неудобно писать их по одному.

Есть ли способ, как, я просто за исключением свойства Image в лямбда-код для более короткого кода?

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Создайте свой собственный метод расширения SelectExcept:

public static IQueryable<T> SelectExcept<T, TKey>(this IQueryable<T> sequence,
    Expression<Func<T, TKey>> excluder)
{
    List<string> excludedProperties = new List<string>();
    if (excluder.Body is MemberExpression memberExpression)
    {
        excludedProperties.Add(memberExpression.Member.Name);
    }
    else if (excluder.Body is NewExpression anonymousExpression)
    {
        excludedProperties.AddRange(anonymousExpression.Members.Select(m => m.Name));
    }
    var includedProperties = typeof(T).GetProperties()
        .Where(p => !excludedProperties.Contains(p.Name));

    return sequence.Select(x => Selector(x, includedProperties));
}

private static T Selector<T>(T obj, IEnumerable<PropertyInfo> properties)
{
    var instance = Activator.CreateInstance<T>();
    foreach (var property in properties)
        property.SetValue(instance, property.GetValue(obj), null);

    return instance;
}

В клиенте:

var result = context.MyItem.SelectExcept(x => x.Image);

Вы можете исключить более одного свойства:

var result = context.MyItem.SelectExcept(x => new { x.Image, x.Name });
0 голосов
/ 10 мая 2018

Для этого вы можете использовать AutoMapper . Просто создайте класс DTO со всеми свойствами, кроме тех, которые вы не хотите запрашивать:

public class MyItemDTO
{
    public int Id { get; set; }

    public string Name { get; set; }
}

Затем добавьте отображение:

Mapper.Initialize(cfg => 
{
    cfg.CreateMap<MyItem, MyItemDTO>();
});

Теперь вы можете запрашивать ваши объекты следующим образом:

context.MyItem
    .OrderBy(m => m.Name)
    .ProjectTo<MyItemDTO>();

Это расширение доступно в AutoMapper.QueryableExtensions.

Вы также можете создать класс DTO со всеми свойствами объекта и затем игнорировать некоторые из них при отображении:

cfg.CreateMap<MyItem, MyItemDTO>().ForMember(d => d.Image, m => m.Ignore());

Если вы используете EF Core , вы можете создать экземпляр класса сущности внутри запроса LINQ, чтобы можно было отобразить сущность на себя и игнорировать некоторые свойства из нее без создания дополнительных классов DTO:

cfg.CreateMap<MyItem, MyItem>().ForMember(d => d.Image, m => m.Ignore());

Затем вы просто используете ProjectTo с типом сущности, который исключает нежелательные свойства из запроса SQL:

context.MyItem
    .OrderBy(m => m.Name)
    .ProjectTo<MyItem>();

Обратите внимание, что вам также может понадобиться создать сопоставления для каждого свойства навигации объекта.

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