Условие строки Entity Framework в списке, связанном с ForeignKey - PullRequest
0 голосов
/ 07 мая 2020

Я пытаюсь составить фильтруемый список c топи. Есть 2 таблицы, связанные с внешним ключом. Я должен написать LINQ-запрос, который будет искать темы по строковому фильтру, отправляемому клиентом, например «SpecId == 2 AND ValueBit == true». Я использовал шаблон репозитория в своем сервисном проекте и пытался это сделать, но не смог реализовать фильтр, как хочу.

  1. x.TopicSpecs.Where (условие) часть не работает, потому что условие является строкой. Я пытался использовать DynamicQueryBuilder, но Linq To Entities его не распознает. x.TopicSpecs.Where (y => y.SpecId == 2 && y.ValueBit == true) работает, он должен кодироваться динамически.
  2. Какой из них правильный, отправка запроса в topicRepository или topicSpecRepository?

Я потратил на это весь день, но не смог решить этот запрос. Не могли бы вы мне помочь?

Мой запрос

Topics = await topicRepository.GetAllWithStringOrder(x => new TopicModel
            {
                CreatedDate = x.CreatedDate,
                Subtitle = x.Subtitle,
                Title = x.Title,
                UpdatedDate = x.UpdatedDate,
                Users = x.User.UserProfiles.Select(y => new UserProfileModel
                {
                    Nickname = y.Nickname
                }).ToList(),
                TopicId = x.TopicId,
                UserId = x.UserId,
                TopicCommentCount = x.TopicComments.Count,
                TopicSpecs = x.TopicSpecs.Where(y => y.Spec.ShowInTopic).Select(y => new TopicSpecModel
                {
                    ValueBit = y.ValueBit,
                    ValueDate = y.ValueDate,
                    ValueNumber = y.ValueNumber,
                    ValueString = y.ValueString,
                    Spec = new SpecModel
                    {
                        Name = y.Spec.Name,
                        SpecId = y.Spec.SpecId,
                        Color = y.Spec.Color
                    }
                }).ToList()
            }, x => x.IsActive && !x.IsDeleted && x.IsLatest && x.TopicSpecs.Where(condition).Count() > 0, model.ItemsPerPage.Value, model.PageNumber.Value, model.SortBy, !model.Reverse)

GetAllWithStringOrder

public virtual async Task<List<TReturn>> GetAllWithStringOrder<TReturn>(Expression<Func<TEntity, TReturn>> selectExp, Expression<Func<TEntity, bool>> whereExp, int itemsPerPage, int pageNumber, string orderBy, bool isDescending, params Expression<Func<TEntity, object>>[] includeExps)
    {
        var query = DbSet.Where(whereExp);
        if (!string.IsNullOrEmpty(orderBy))
            query = query.OrderBy(orderBy);
        if (includeExps != null)
            query = includeExps.Aggregate(query, (current, exp) => current.Include(exp));
        query = query.OrderBy(orderBy, isDescending).Skip<TEntity>((pageNumber - 1) * itemsPerPage).Take<TEntity>(itemsPerPage);
        return await query.Select(selectExp).ToListAsync();
    }

Topi c Таблица

public partial class Topic
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Topic()
    {
        this.TopicComments = new HashSet<TopicComment>();
        this.TopicContents = new HashSet<TopicContent>();
        this.TopicSpecs = new HashSet<TopicSpec>();
    }

    public int TopicId { get; set; }
    public string Title { get; set; }
    public string Subtitle { get; set; }
    public int UserId { get; set; }
    public System.DateTimeOffset CreatedDate { get; set; }
    public Nullable<System.DateTimeOffset> UpdatedDate { get; set; }
    public bool IsDeleted { get; set; }
    public bool IsLatest { get; set; }
    public bool IsActive { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<TopicComment> TopicComments { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<TopicContent> TopicContents { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<TopicSpec> TopicSpecs { get; set; }
    public virtual User User { get; set; }
}

TopicSpe c Table

public partial class TopicSpec
{
    public int TopicSpecId { get; set; }
    public int TopicId { get; set; }
    public int SpecId { get; set; }
    public string ValueString { get; set; }
    public Nullable<bool> ValueBit { get; set; }
    public Nullable<System.DateTimeOffset> ValueDate { get; set; }
    public Nullable<int> ValueNumber { get; set; }
    public bool IsActive { get; set; }

    public virtual Spec Spec { get; set; }
    public virtual Topic Topic { get; set; }
}

Spe c Table

public partial class Spec
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Spec()
    {
        this.TopicSpecs = new HashSet<TopicSpec>();
    }

    public int SpecId { get; set; }
    public int SpecTypeId { get; set; }
    public string Name { get; set; }
    public bool IsActive { get; set; }
    public bool ShowInTopic { get; set; }
    public string Color { get; set; }

    public virtual SpecType SpecType { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<TopicSpec> TopicSpecs { get; set; }
}

1 Ответ

0 голосов
/ 07 мая 2020

Где-то у вас есть класс модели, из которого этот запрос извлекает свойства для выполнения, как указано в последней строке этого запроса:

.....  model.ItemsPerPage.Value, model.PageNumber.Value, ....

Было бы полезно, если бы этот класс также был опубликован, хотя это уже довольно много кода, который нужно проанализировать.

Тем не менее, самое простое решение вопроса №1 - это, вероятно, добавить некоторые свойства к этому классу model и использовать их в предложении Where.

... x.TopicSpecs.Where(y=> y.SpecId == model.SpecIdValue && y.ValueBit == model.ValueBitFlag)....

В этом примере новые свойства модели: model.SpecIdValue как int и model.ValueBitFlag как bool.

Я предполагаю, что у вас есть этот вызов Topics = await topicRepository.GetAllWithStringOrder... внутри другого вызываемого вами метода, поэтому вы можете установить свойства модели, о которых я упоминал выше, и снова вызвать этот метод, чтобы получить обновленный ответ.

Для вопроса № 2, если вы ищете список типа Topic в качестве результата запроса, вам следует использовать topicRepository.

...