How to write dynamic Linq to count matching numbers

断了今生、忘了曾经 提交于 2019-12-14 04:20:27

问题


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:

Ticket:
TicketId, Name, AddDateTime

TicketNumbers:
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!


回答1:


 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
             .Count(tk=>
                       targetDate < tk.AddDateTime &&  tk.AddDateTime < tooLate
                       &&  arr.All(n=> tk.TicketNumbers.Any(tn=>tn.Number== n));



回答2:


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)))


来源:https://stackoverflow.com/questions/25694403/how-to-write-dynamic-linq-to-count-matching-numbers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!