У меня есть следующий код для фильтрации моих данных:
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]) '
Я покажу вам этот момент с помощью отладчика.
Первый случай. Здесь все в порядке:
Второй случай:
У меня не будет kek2
, потому что будет описано описанное исключение.
Так что не так? Невозможно использовать Except
для IQuareable
?
Здесь я покажу исходный код репозитория customers
:
public class CustomerRepository : ICustomerRepository
{
private readonly ApplicationDbContext _applicationContext;
public CustomerRepository(ApplicationDbContext applicationContext)
{
_applicationContext = applicationContext;
}
public IQueryable<Customer> Customers => _applicationContext.Customers;
...