Как мне запросить базу данных SQL Server со списком параметров в Dapper?

#c# #sql-server #dapper

#c# #sql-server #dapper

Вопрос:

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

Это то, что я пробовал:

 public async Task<IEnumerable<Animal>> GetAnimalsFromAttributesAsync(IEnumerable<AnimalInfo> attributeSets)
{
    using (var myDB = new SqlConnection(connectionString))
    {
        await myDB.OpenAsync();
        var results = new List<Animal>();

        foreach (var attributeSet in attributeSets)
        {
            var sql = @"select AnimalID, AnimalTypeID, AnimalColor
                        from Animals
                        where AnimalTypeID = @AnimalTypeID 
                          and AnimalColorID = @AnimalColorID";

            var result = myDB.Query<Animal>(sql, attributeSet);
            results.AddRange(result);
        }

        return results
    }
}
  

Это нормально работает для небольшого количества свойств. Но если у меня много свойств, то я получаю эту ошибку:

Ошибка: входящий запрос содержит слишком много параметров. Сервер поддерживает максимум 2100 параметров. Уменьшите количество параметров и повторно отправьте запрос.

Есть ли лучший способ сделать это?

Комментарии:

1. Вы действительно запрашиваете базу данных с помощью предложения where с 2k параметрами одновременно?

2. Привет — что AnimalInfo здесь? Я изо всех сил пытаюсь понять, почему это вызывает взрыв параметров (контекст: я основной автор dapper)

3. Попробуйте использовать оператор SQL «in» и укажите свои идентификаторы в виде массива.

4. что-то, что нужно попробовать: var result = myDB.Query<Animal>(sql, new { attributeSet.AnimalTypeId, attributeSet.AnimalColorID }); — должно сделать невозможным возникновение чего-либо слишком странного

5. Там вполне может быть 3000 сведений, но ваш запрос принимает только два параметра одновременно — вам нужно было бы выполнить его 3000 раз. Альтернативой может быть запрос на основе TVP.

Ответ №1:

Благодаря предложению @MarcGravell я решил переписать свой запрос как запрос TVP.

SQL:

 create type AnimalInfo as table
( 
    AnimalTypeID int,
    AnimalColorID int
)
go  
  

C#:

 public async Task<IEnumerable<Animal>> GetAnimalsFromAttributesAsync(DataTable attributeSets)
{
    using (var myDB = new SqlConnection(connectionString))
    {
        await myDB.OpenAsync();

        var sql = @"select AnimalID, AnimalTypeID, AnimalColor
                    from Animals
                    inner join @animalInfos animalInfos on 
                        animalInfos.AnimalColorID = Animals.ColorID 
                            and 
                        animalInfos.AnimalTypeID = Animals.AnimalTypeID";

        var result = await myDB.QueryAsync<Animal>(sql, new { animalInfos = attributeSets.AsTableValuedParameter("AnimalInfo") };

        return resu<
    }
}