Метод LINQ Except дает мне System.ArgumentException для IQuareable - PullRequest
0 голосов
/ 11 октября 2019

У меня есть следующий код для фильтрации моих данных:

public List<Customer> ShowCustomersForCurrentTemplate(PushTemplate pushTemplate)
{
    string templateType = pushTemplate.TemplateType;

    string timeType = pushTemplate.IntervalType;

    DateTime clientStartDate = pushTemplate.ClientStartDateTime;

    int eventOlderThan = pushTemplate.EventOlderThan;

    int eventYoungerThan = pushTemplate.EventYoungerThan;

    List<string> langs = pushTemplate.Messages?.Select(x => x.PushLang?.LangCode).ToList() ??
                         new List<string>();

    List<string> packageIds = pushTemplate.PackageIds ?? new List<string>();

    List<string> advertisers = pushTemplate.AdvertiserPushTemplates?.Select(x => x.Advertiser?.Name).ToList() ??
                               new List<string>();

    string category = pushTemplate.Category?.Name;

    DateTime eventOlderThanDate = DateTime.UtcNow;

    DateTime eventYoungerThanDate = DateTime.UtcNow;

    if (timeType == "days")
    {
        eventOlderThanDate = eventOlderThanDate.AddDays(0 - eventOlderThan);
        eventYoungerThanDate = eventYoungerThanDate.AddDays(0 - eventYoungerThan);
    }
    else if (timeType == "minutes")
    {
        eventOlderThanDate = eventOlderThanDate.AddMinutes(0 - eventOlderThan);
        eventYoungerThanDate = eventYoungerThanDate.AddMinutes(0 - eventYoungerThan);
    }

    var customers = _customerRepository.Customers
        .Include(x => x.Application)
            .ThenInclude(x => x.Advertiser)
                .ThenInclude(x => x.Category)
            .Include(x => x.CustomerEvents)
        .Select(x => x);

    // selection by category
    customers = customers.Where(x => x.Application.Advertiser.Category.Name == category);

    // selection by advertisers
    customers = customers.Where(x => advertisers.Contains(x.Application.Advertiser.Name));

    // selection by applications
    customers = customers.Where(x => packageIds.Contains(x.Application.AppId));

    // selection by locales
    customers = customers.Where(x => langs.Contains(x.Locale));

    if (templateType == "registration_and_not_deposit")
    {
        // selection by event type
        customers = customers.Where(x => x.CustomerEvents
            .Any(y => y.Customer.CreatedAt > clientStartDate && y.CreatedAt <= eventOlderThanDate &&
                      y.CreatedAt >= eventYoungerThanDate && y.EventType == "registration"));

        // set of redundant events  
        var customersWithEventsForException =
            customers.Where(x => x.CustomerEvents.Any(y => y.EventType == "deposit"));

            // filter redundant events
            customers = customers.Except(customersWithEventsForException);
    }
    else if (templateType == "opened_and_not_registration")
    {
        // отбор по типу события
        customers = customers.Where(x => x.CustomerEvents
            .Any(y => y.Customer.CreatedAt > clientStartDate && y.CreatedAt <= eventOlderThanDate &&
                      y.CreatedAt >= eventYoungerThanDate && y.EventType == "open"));

        // selection be event
        var customersWithEventsForException =
            customers.Where(x => x.CustomerEvents.Any(y => y.EventType == "registration"));

        // filter redundant events
        customers = customers.Except(customersWithEventsForException);
    }

    // set of users who already had push
    var alreadyHavePush = _pushRepository.Pushes
        .Include(x => x.Customer)
        .Where(x => x.PushTemplate.PushTemplateId == pushTemplate.PushTemplateId && x.Sent)
        .Select(x => x.Customer);

    // filter users, who already had push
    var res = customers.Except(alreadyHavePush).Select(x => x).ToList();

    return res;
}

Извините за длинный метод, но это довольно просто. Сделай Where для IQueryable снова и снова, затем я использую .ToList() для получения отфильтрованного результата.

Хорошо, о проблеме. Мне кажется, что метод Except дает мне

System.ArgumentException: выражение типа 'System.Collections.Generic.IEnumerable 1[Microsoft.EntityFrameworkCore.Query.Internal.AnonymousObject]' cannot be used for parameter of type 'System.Collections.Generic.IEnumerable 1 [System.Object]' метода 'System.Collections.Generic.IEnumerable 1[System.Object] Except[Object](System.Collections.Generic.IEnumerable 1 [System.Object], System.Collections.Generic.IEnumerable`1 [System.Object]) '

Я покажу вам этот момент с помощью отладчика.

Первый случай. Здесь все в порядке:

enter image description here

Второй случай:

enter image description here

У меня не будет kek2, потому что будет описано описанное исключение.

Так что не так? Невозможно использовать Except для IQuareable?

Здесь я покажу исходный код репозитория customers:

public class CustomerRepository : ICustomerRepository
{
    private readonly ApplicationDbContext _applicationContext;

    public CustomerRepository(ApplicationDbContext applicationContext)
    {
        _applicationContext = applicationContext;
    }

    public IQueryable<Customer> Customers => _applicationContext.Customers;
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...