Можно ли сопоставить результат с Tuple в Dapper?

Я пытаюсь выбрать список из 2 целых столбцов, сопоставляя результаты с Tuple. Как пример:

return connection.Query<Tuple<int,int>>("select id1, id2 from sometable").ToList();

не работает, но тот же запрос работает, если я создаю класс с двумя целыми числами, например:

return connection.Query<BogusClass>("select id1, id2 from sometable").ToList();

public class BogusClass{
public int id1 {get;set;}
public int id2 {get;set;}
}

Мое предпочтение заключается не в том, чтобы создать какой-то фиктивный класс, чтобы получить некоторые данные для работы. В этом случае это два целых столбца, но есть и другие варианты использования, которые я мог придумать.

Изменить - Ответ: Это синтаксис, который работал у меня HTH

изменения:

return connection.Query<Tuple<int,int>>("select id1, id2 from sometable").ToList();

в

return connection.Query<int, int, Tuple<int, int>>("select id1, id2 from sometable", Tuple.Create, splitOn: "*").ToList();

Ответы

Ответ 1

Вот рабочий пример:

public class DapperTests
{
    [Test]
    public void TuppleTest()
    {
        var conn = new SqlConnection(@"Data Source=.\sqlexpress; Integrated Security=true; Initial Catalog=mydb");
        conn.Open();

        var result = conn.Query<int, int, Tuple<int, int>>(
            "select 1,2 union all select 4,5", Tuple.Create, splitOn: "*").ToList();

        conn.Close();

        Assert.That(result.Count, Is.EqualTo(2));
    }
}

Ниже вы можете найти примеры .

Ответ 2

Это работает, начиная с С# 7. Это кортеж значения

public (int Id, DateTime? PublishDate) GetItem(string id)
{
    const string sqlCommand = "select top 1 Id, PublishDate from Item where Id = @id";

    return _connection.Query<(int, DateTime?)>(sqlCommand, new { id }).FirstOrDefault();
}       

Используя метод

var item = GetItem(123);
Console.WriteLine($"The publish date of item [{item.Id}] is [{item.PublishDate.Value}]");

Убедитесь, что вы установили Dapper 1.50.4 или новее.

Ответ 3

Tuple - один из вариантов, я предпочитаю использовать динамический результат, когда я не хочу создавать класс, т.е.

string sql = "Select 'f' as Foo, 'b' as Bar";

var result = connection.Query<dynamic>(sql).Single();

string foo = result.Foo;
string bar = result.Bar

Имя поля, возвращаемого из результата, будет именем динамического свойства.

В вашем случае вы хотите вернуть список и не назначать одиночные переменные, поэтому более подходящим является Tuple:

string sql = "select id1, id2 from sometable";

List<Tuple<int, int>> result = conn.Query<int, int, Tuple<int, int>>( // *1
    sql,
    Tuple.Create, // *2
    splitOn: "*" ) // *3
    .AsList(); // *4

* 1 = <int,int, Tuple<int, int>> сообщает dapper, что будут два целых числа, которые вернут Tuple

* 2 = указывает dapper использовать Tuple для возврата результата

* 3 = указывает dapper, что каждое возвращаемое поле используется для возврата результата для каждого свойства кортежа.

* 4 = Метод расширения Dapper для приведения внутреннего результата Dapper к List; по умолчанию Dapper возвращает список под обложками, поэтому приведение будет быстрее, чем копирование в новый список.

Ответ 4

Вам может понравиться

string query = "Select value1 as Item1,value2 as Item2 from #sometable";
var data = db.Query<Tuple<int,int>>(query);

Ответ 5

Для тех, кто использует асинхронность, это может быть достигнуто с помощью ValueTuple.

var res = await conn.QueryAsync<(int Id1, int Id2)>(sql);

List<Tuple<int, int>> tuples = res.Select(x => new Tuple<int, int>(x.Id1, x.Id2)).ToList();