tghamm / dynamic-linq-query-builder

A truly generic and dynamic linq query builder to compliment jQuery QueryBuilder and other dynamic linq query generation needs
MIT License
256 stars 110 forks source link

Issue with implementing filtering on nested collection #63

Closed harpsicord86 closed 4 years ago

harpsicord86 commented 4 years ago

Hi there,

I'm having an issue with trying to implement a filter on a nested collection. I have the following ViewModel set up:

`public class MailoutViewModel { private int MailoutTotal => Mailouts.Count(); private int ResponseTotal => Responses.Count();

    public int ParticipantId { get; set; }
    public bool HaveAnyMailouts => MailoutTotal > 0;
    public bool HaveAnyResponses => ResponseTotal > 0;
    public int NoOfDaysSinceActive 
    {
        get
        {
            var active = Responses.FirstOrDefault(x => x.Type.Code == "Y2");
            if (active != null)
            {
                return (int)(DateTime.Now - active.DataReceived).TotalDays;
            }
            return 0;
        }
}

    public IEnumerable<MailComm> Mailouts { get; set; }
    public IEnumerable<Response> Responses { get; set; }
    public IEnumerable<CustomItem> CustomItems { get; set; }
    public IEnumerable<ConsentItem> ConsentItems { get; set; }

}`

I'm using this so that I can query several tables to check if a participant has a mailout due e.g. if they have a particular response but no letter has been sent then we can send them a specific letter.

I've implemented as such: ` var searchFilterTest = new QueryBuilderFilterRule() { Condition = "and", Rules = new List() { new QueryBuilderFilterRule() { Condition = "and", Field = "HaveAnyMailouts", Id = "HaveAnyMailouts", Operator = "equal", Type = "boolean", Value = new [] { "true" } }, new QueryBuilderFilterRule() { Condition = "and", Field = "HaveAnyResponses", Id = "HaveAnyResponses", Operator = "equal", Type = "boolean", Value = new [] { "true" } }, new QueryBuilderFilterRule() { Condition = "and", Id = "Responses.Ambiguous", Field = "Responses.Ambiguous", Input = "NA", Operator = "equal", Type = "boolean", Value = new[] {"false"} } } };

        var mailouts = _participantManager.GetAll().Where(x => x.Responses.Any()).Select(x => new MailoutViewModel()
        {
            ParticipantId = x.ParticipantId,
            Mailouts = x.Mailouts,
            Responses = x.Responses,
            CustomItems = x.CustomItems,
            ConsentItems = x.Consent
        });

var result = mailouts.BuildQuery(searchFilterTest).ToList(); ` However, upon building the query, I'm getting a System.ArgumentNullException: 'Value cannot be null. Parameter name: property'

Here is my Response class: `public class Response : BaseEntity { public Response() { ResponseItems = new List(); }

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ResponseId { get; set; }
    public int ParticipantId { get; set; }
    public int TypeId { get; set; }
    [Index]
    public DateTime DataReceived { get; set; }
    [Index]
    public bool Ambiguous { get; set; }

    #region Navigation properties

    public virtual Participant Participant { get; set; }
    public virtual ResponseType Type { get; set; }
    public virtual OptOut OptOut { get; set; }
    public virtual ICollection<ResponseItem> ResponseItems { get; set; }
    #endregion
}`

I've been following your example within your Unit Test but it doesn't seem to work (also it's worth noting that in your unit test, you are using FilterRule which has been marked as deprecated!).

Can someone offer any advice please?

harpsicord86 commented 4 years ago

I think I've finally solved it...

In my MailoutViewModel, I was using IEnumerable instead of List. Because of using an interface, it could not find the property within the list.

Thanks anyway :-) this is a great library and I'm looking forward to using it in my project.

MorgeMoensch commented 1 month ago

In my MailoutViewModel, I was using IEnumerable instead of List. Because of using an interface, it could not find the property within the list.

Thanks @harpsicord86 , that was my issue as well! Thank you for commenting your solution and not leave the thread without an answer