いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

iBatis.NET奮闘記-009 (IDictionaryにて結果を取得) (Mapper, QueryForDictionary, IDictionary)


iBatis.NETには、Java版と同じくIDictionary(javaでいうMap)で結果を取得できる機能があります。
使用するメソッドは、QueryForDictionaryとなります。このメソッドもQueryForListと同じくジェネリック対応
となっています。


QueryForDictionaryメソッドには、2つのパターンがあります。

QueryForDictionary(string statementName, object parameterObject, string keyProperty, string valueProperty)

の方は、結果データの中からkeyPropertyで指定したカラムの値をDictionaryのキーとし、valuePropertyで指定したカラムの値
をDictionaryの値として返してきます。


例えば以下のように使います。

QueryForDictionary("Author.FindAuthors", null, "Id", "Name")

上記の場合だと、Author.FindAuthorsクエリの結果列の内、IdをキーとしてNameを値としたDictionaryが帰ってきます。


もう一つのパターンは、以下のものです。

QueryForDictionary(string statementName, object parameterObject, string keyProperty)

このパターンでは、keyPropertyのみを指定します。帰ってくるDictionaryは、クエリの結果をいつも通りマッピングした結果の
データオブジェクトとなります。以下のようにして使用します。

QueryForDictionary("Author.FindAuthors", null, "Id")

上記の場合だと、Author.FindAuthorsクエリの結果列の内、Idをキーとしてクエリのマッピング結果を値としたDictionaryが帰ってきます。
注意点として、このパターンのメソッドを使用する場合は、必ずSQL定義ファイルにてresultMapの設定が必要になります。



てことで、以下サンプルです。


[Author.cs]

using System;
using System.Collections.Generic;

namespace Gsf.Samples.IBatisNet.Models {

    public class Author {

        int    _id;
        string _name;
        int    _age;

        public int Id{
            get{ return _id; }
            set{
                _id = value;
            }
        }

        public string Name{
            get{ return _name; }
            set{
                _name = value;
            }
        }

        public int Age{
            get{ return _age; }
            set{
                _age = value;
            }
        }

        public override string ToString() {
            return string.Format("id:{0}, name:{1}, age:{2}", Id, Name, Age);
        }
    }
}

[Author.ibatis.xml]

<?xml version="1.0" encoding="utf-8" ?>
<sqlMap namespace="Author"
        xmlns="http://ibatis.apache.org/mapping"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <alias>
        <typeAlias type="Gsf.Samples.IBatisNet.Models.Author" alias="Author"/>
    </alias>

    <resultMaps>
        <!--
            結果をIDictionary<K, V>で返却するには、必ずresultMapが必要となる。
            (resultMapを定義しないと、エラーとなる。)
            
            resultMapでマッピングするのは、マップの値となるオブジェクトの分を設定する。
            キーの分については、自動的にマッピングが行われる。
        -->
        <resultMap id="find-authors-result" class="Author">
            <result column="Id"   property="Id"/>
            <result column="Name" property="Name"/>
            <result column="Age"  property="Age"/>
        </resultMap>
    </resultMaps>
    
    <statements>
        <select id="FindAuthors" resultMap="find-authors-result">
            <![CDATA[
                select
                     a.AuthorId as Id
                    ,a.Name     as Name
                    ,a.Age      as Age
                from
                    Authors a
            ]]>
        </select>
    </statements>
</sqlMap>

[テストユニット]

using System;
using System.Collections.Generic;

using Gsf.Samples.IBatisNet.Models;

using IBatisNet.Common;
using IBatisNet.DataMapper;

using NUnit.Framework;

namespace Gsf.Samples.IBatisNet {

    [TestFixture]
    public class IBatisSample009 {

        [Test]
        public void IDictionaryで結果を取得(){
            //
            // キーにAuthorId, 値としてNameをマッピングしてIDictionaryを取得する場合
            //
            IDictionary authorNamesMap = Mapper.Instance().QueryForDictionary("Author.FindAuthors", null, "Id", "Name");

            foreach(KeyValuePair pair in authorNamesMap) {
                Console.WriteLine("key:{0}, value:{1}", pair.Key, pair.Value);
            }
            

            //
            // キーにAuthorId, 値としてAuthorオブジェクトをマッピングしてIDictionaryを取得する場合
            //
            IDictionary authorsMap = Mapper.Instance().QueryForDictionary("Author.FindAuthors", null, "Id");

            Assert.IsNotNull(authorsMap);
            Assert.AreNotEqual(0, authorsMap);

            foreach(KeyValuePair pair in authorsMap){
                Console.WriteLine("key:{0}, value:{1}", pair.Key, pair.Value);
            }
        }
    }

    class DummyEntryPoint009{

        static void Main(){
            //
            // nop;
            //
        }
    }
}


上記を実行すると、例えば以下のように出力されます。

key:1, value:gsf_zero1
key:2, value:gsf_zero2
key:3, value:gsf_zero3
key:1, value:id:1, name:gsf_zero1, age:28
key:2, value:id:2, name:gsf_zero2, age:29
key:3, value:id:3, name:gsf_zero3, age:30