Запрос Dapper со списком параметров

Я пытаюсь запустить запрос с помощью Dapper с известным набором параметров, но со списком значений для этих параметров. Простым примером того, что я пытаюсь сделать, было бы:

DateTime endDate = DateTime.Now;
DateTime startDate = endDate.AddHours(-24);

string query = "select COUNT(*) from Test where Status = @Status AND DateCreated <= @Hour;";
var stuff = con.Query(query, (startDate).ByHourTo(endDate).Select(hour => new
{
     Status = 1,
     Hour = hour,
}));

Dapper создает исключение с "параметром" @Status "должен быть определен". Я знаю, что Dapper может обрабатывать списки параметров при выполнении массовых вставок и обновлений, но не может ли он сделать это для выбора?

4 ответов


попробуйте это:

List<string> names = new List<string> { "Bob", "Fred", "Jack" };
string query = "select * from people where Name in @names";
var stuff = connection.Query<ExtractionRecord>(query, new {names});

Я знаю, что опаздываю на эту вечеринку, но, думаю, я понимаю, что этот запрос означает, что вы просто хотите передать некоторые свойства и создать свой запрос на основе этих динамических свойств.

С кодом ниже я могу использовать любой тип, а затем просто заполнить и передать объект этого типа с несколькими значениями (я называю это мой объект запроса), и запрос будет сгенерирован, чтобы найти объекты, соответствующие значениям, которые вы установили в своем объекте запроса.

*быть осторожны, значений и вещи, которые имеют значения по умолчанию.

Динамический Запрос

    public IEnumerable<T> Query<T>(T templateobject) {
        var sql = "SELECT * From " + typeof(T).Name + " Where ";

        var list = templateobject.GetType().GetProperties()
             .Where(p => p.GetValue(templateobject) != null)
             .ToList();

        int i = 0;

        Dictionary<string, object> dbArgs = new Dictionary<string, object>();

        list.ForEach(x =>
        {
            sql += x.Name + " = @" +  x.Name;

            dbArgs.Add(x.Name, x.GetValue(templateobject));

            if (list.Count > 1 && i < list.Count - 1) {
                sql += " AND ";
                i++;
            }
        });

        Debug.WriteLine(sql);

        return _con.Query<T>(sql, dbArgs).ToList();
    }

использование

*repo-это класс, который содержит вышеуказанную функцию

var blah = repo.Query<Domain>(new Domain() { Id = 1, IsActive=true });

выход

SELECT * From Domain Where Id = @Id AND IsActive = @IsActive

затем он выплевывает любые "домены", которые соответствуют вышеуказанному запросу.


DECLARE @Now datetime
SET @Now = getdate()

SELECT
    DATEADD( hh, -n, @Now ) AS StartDate,
    DATEADD( hh, -n+1, @Now ) AS EndDate
INTO
    #DateRanges
FROM 
    Numbers
WHERE
    n <= 24

SELECT
    COUNT(*) AS [Count],
    #DateRanges.StartDate
FROM
    Test
        JOIN
    #DateRanges
        ON Test.DateCreated >= #DateRanges.StartDate
        AND Test.DateCreated < #DateRanges.EndDate
GROUP BY
    #DateRanges.StartDate

вот как я бы это сделал, но это предполагает одно: у вас есть таблица в вашей базе данных с именем "Numbers", в которой есть произвольное число целых чисел, по одному на строку, начиная с 1, С по крайней мере 24 числами в нем.

то есть, таблица выглядит так:

n
-----
1
2
3
4
5
...

если у вас нет такой таблицы, очень быстро и легко сделать ее только для этой команды:

CREATE TABLE #Numbers
(
    n int
)

SET NOCOUNT ON

INSERT #Numbers values (1);
GO
INSERT #Numbers SELECT n + (SELECT COUNT(*) FROM #Numbers) FROM #Numbers
GO 16 --execute batch 16 times to create 2^16 integers.

вы не можете иметь несколько пакетов в хранимой процедуре, но вы можете в текстовой команде. GO 16 запускает предыдущий пакет 16 раз. Если вам это нужно в хранимой процедуре, вы можете повторить второй