web-dev-qa-db-ja.com

Dapperでタプルに結果をマッピングできますか?

結果をタプルにマップする2つの整数列のリストを選択しようとしています。例として:

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

は機能しませんが、次のような2つの整数を持つクラスを作成すると、同じクエリが機能します。

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

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

私の好みは、データを処理するためだけに偽のクラスを作成する必要がないことです。この場合は2つの整数列ですが、他にも考えられる使用例があります。

編集-回答:これは私のために働いた構文です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();
26
Tom Gerken

これが実際の例です:

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

他の例 ここ を見つけることができます。

21
Void Ray

あなたはそうすることができます

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

これはC#7から機能します。これは Value Tuple です。

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以降がインストールされていることを確認してください。

15
Rubanov

タプルは1つのオプションです。クラスを作成したくない場合は常に動的な結果を使用します。つまり、

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

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

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

結果から返されるフィールドの名前は、動的プロパティの名前になります。

あなたのケースでは、単一の変数に割り当てるのではなく、リストを返したいので、タプルがより適切でしょう:

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>>は、タッパーを返す2つの整数があることをdapperに通知します

* 2 =タッパーを使用して結果を返すようにdapperに指示します

* 3 =返されるすべてのフィールドがタプルの各プロパティの結果を返すために使用されることをdapperに伝えます。

* 4 = Dapperの内部結果をListにキャストするDapper拡張メソッド。デフォルトでは、Dapperはカバーの下にリストを返すため、キャストは新しいリストにコピーするよりも速くなります。

14
Metro Smurf

非同期を使用している場合は、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();
2
judehall