How to write dynamic Linq to count matching numbers c# dynamic-linq entity-framework linq


I have two tables in database. Ticket and TicketNumbers. I would like to write Linq to count the number of tickets that have numbers matching those passed into this function. Since we don't know how many numbers must be matched, the Linq has to be dynamic ... to my understanding.

public int CountPartialMatchingTicket(IList<int> numbers)
    // where's the code? =_=;

Say for example there are 3 Tickets in the database now and I want to count up all those that have the numbers 3 and 4.

(1) 1 2 3 4
(2) 1 3 4 6 7
(3) 1 2 3

In this case the function should return 2, since ticket (1) and (2) have the matching numbers. In another case if asked to match 1, 2, 3, then again we should be returned 2.

Here's what those two tables in the database look like:

TicketId, Name, AddDateTime

Id, TicketId, Number

I've never used Dynamic Linq before, so just in case this is what I have at the top of my cs file.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using LottoGen.Models;
using System.Linq.Dynamic;

First things first though, I don't even know how I should write the Linq line for a fixed amount of numbers. I suppose the SQL would be like this:

SELECT        TicketId, COUNT(0) AS Expr1
FROM          TicketNumber
WHERE         (Number = 3) OR (Number = 4)
GROUP BY      TicketId

However this isn't what I want either. The above query would get me Tickets that have either a 3 or a 4 - but I just want the tickets that have BOTH numbers. And I guess it has to be nested somehow to return a single count. If I had to use my imagination for completing the function then, it would be something like this:

public int CountPartialMatchingTicket(IList<int> numbers)
    string query = "";
    foreach(int number in numbers) {
        query += "Number = " + number.ToString() + " AND ";
    // I know.. there is a trailing AND.. lazy
    int count = DbContext.TicketNumbers.Where(query).Count();
    return count;

Oh wait a minute. There's no Dynamic Linq there... The above is looking like something I would do in PHP and that query statement obviously does not do anything useful. What am I doing? :(

At the end of the day, I want to output a little table to the webpage looking like this.

Ticket             Matching Tickets
3 4                               2

Trinity, help!

9/5/2014 9:44:25 PM

Accepted Answer

 public int CountPartialMatchingTicket(IList<int> numbers)
     var arr = numbers.ToArray();
     int count = DbContext.Tickets
             .Count(tk=>arr.All(n=> tk.TicketNumbers.Any(tn=>tn.Number== n));
     return count;

UPDATE: "If you don't mind, how would I limit this query to just the tickets made on a particular AddDateTime (the whole day)?"

The part inside the Count() method call is the WHERE condition, so just extend that:

    DateTime targetDate = ......;
    DateTime tooLate = targetDate.AddDay(1);

     int count = DbContext.Tickets
                       targetDate < tk.AddDateTime &&  tk.AddDateTime < tooLate
                       &&  arr.All(n=> tk.TicketNumbers.Any(tn=>tn.Number== n));
9/8/2014 9:32:24 PM

Popular Answer

This is similar to James Curran's answer, but a little simpler, and it should produce a simpler WHERE IN-based query:

// count all tickets...
return DbContext.Tickets.Count(
    // where any of their ticket numbers
    tk => tk.TicketNumbers.Any(
        // are contained in our list of numbers
        tn => numbers.Contains(tn.Number)))

Related Questions

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow