[Spring.Net]RowMapper With Delegate

  • 7073
  • 0

[Spring.Net]RowMapper With Delegate

前言

之前在介紹Spring.Net的AdoTemplate時,通常會講到一個輕量級的OR mapping動作,叫做RowMapper。也就是透過一個class實作Spring.Data.Generic的IRowMapper<T>,來達到把Relational Data對應到object的property,並在mapping過程做相對應的處理。可以看一下之前文章中有介紹到:[Spring.Net]AdoTemplate回傳IList<T>


然而,通常這個class會將要return的object或IList<object>所有property都與datareader的欄位做binding,當遇到一張table有一兩百個欄位,但實際需求只要取一欄或兩欄時,這樣的mapping過程是相當耗時,會降低許多performance的。而為了這些動態的欄位需求,可能一欄、兩欄、不固定的欄位,難道都要新增對應的class去實作IRowMapper<T>嗎?還是就捨棄OR mapping的好處,改用DataTable回傳呢?

這邊要介紹個簡單的方法,其實就只是delegate,把RowMapper的動作改為Delegate一個匿名function,拋棄式的RowMapper。(可以用過一次就拋棄,或是用了多次再拋棄)。

(感謝J妹幫忙實作出來)

作法

先舉之前RowMapper的作法來當作比較,之前的RowMapper class長這樣:


    public class ColumnSortRowMapper : IRowMapper<ColumnSort>
    {

        #region IRowMapper<ColumnSort> 成員

        ColumnSort IRowMapper<ColumnSort>.MapRow(IDataReader reader, int rowNum)
        {
            ColumnSort columnSort = new ColumnSort();

            columnSort.FunctionID = CovertType.DBToString(reader["FUN_ID"]);
            columnSort.ColumnName = CovertType.DBToString(reader["COL_NAME"]);
            columnSort.ColumnDescription = CovertType.DBToString(reader["COL_DESC"]);
            columnSort.ColumnSEQ = Convert.ToInt16(reader["COL_SEQ"]);
            columnSort.EntryID = CovertType.DBToString(reader["ENTRY_ID"]);
            columnSort.EntryDate = CovertType.DBToString(reader["ENTRY_DATE"]);
            columnSort.EntryTime = CovertType.DBToString(reader["ENTRY_TIME"]);
            columnSort.ModifyID = CovertType.DBToString(reader["MODIFY_ID"]);
            columnSort.ModifyDate = CovertType.DBToString(reader["MODIFY_DATE"]);
            columnSort.ModifyTime = CovertType.DBToString(reader["MODIFY_TIME"]);
            return columnSort;
        }

        #endregion
    }


怎麼使用呢?


return AdoTemplate.QueryWithRowMapper<ColumnSort>(CommandType.Text, sql, new ColumnSortRowMapper(), objParameters);

透過這樣的用法,ColumnSortRowMapper就類似GridView的RowDataBound一樣,會根據撈到多少筆資料,就會assign多少個object到IList<ColumnSort>裡面。

假設我現在只要撈[FUN_ID]與[COL_NAME]兩欄呢?我們可以改寫成這樣:


            return AdoTemplate.QueryWithRowMapperDelegate<ColumnSort>(CommandType.Text, sql, delegate(IDataReader dataReader, int rowNum)
            {
                ColumnSort columnSort = new ColumnSort();
                columnSort.FunctionID = CovertType.DBToString(dataReader["FUN_ID"]);
                columnSort.ColumnName = CovertType.DBToString(dataReader["COL_NAME"]);
                return columnSort;
            }
                , objParameters);


只需要將原本QueryWithRowMapper<T>改成QueryWithRowMapperDelegate<T>,接著把原本放置RowMapper class的參數位置,改為delegate(IDataReder, int),在delegate的function中進行需要的mapping與處理即可。

如此一來就可以避免domain object property過多,在做ORM的時候performance太差的問題。
透過這樣也不需要每次都撈table的所有欄位,只要撈需要的欄位即可。


結論

要轉成用Lammda表示式搞不好也可以,不過沒啥太大差異啦。希望這個小技巧,可以幫助大家不用每次都return DataTable或是每次都mapping所有欄位。


參考

Spring.Net Document:http://www.springframework.net/docs/1.3.0/reference/html/ado.html

Document中的程式碼:


        public virtual IList<Customer> GetCustomersWithDelegate()
        {
            return AdoTemplate.QueryWithRowMapperDelegate<Customer>(CommandType.Text, cmdText,
                        delegate(IDataReader dataReader, int rowNum)
                            {
                                Customer customer = new Customer();
                                customer.Address = dataReader.GetString(0);
                                customer.City = dataReader.GetString(1);
                                customer.CompanyName = dataReader.GetString(2);
                                customer.ContactName = dataReader.GetString(3);
                                customer.ContactTitle = dataReader.GetString(4);
                                customer.Country = dataReader.GetString(5);
                                customer.Fax = dataReader.GetString(6);
                                customer.Id = dataReader.GetString(7);
                                customer.Phone = dataReader.GetString(8);
                                customer.PostalCode = dataReader.GetString(9);
                                customer.Region = dataReader.GetString(10);
                                return customer;
                            });
        }

 

 

 

 


blog 與課程更新內容,請前往新站位置:http://tdd.best/