看到一段某公司對外服務的系統的程式碼,這段程式碼寫好不到一年,而這段程式碼在做一件事情,把從資料庫撈到的資料轉成物件集合,做法就是用 ADO.NET 產生 SqlDataReader,再將 SqlDataReader 丟到一個靜態方法,在靜態方法裡面逐筆讀取資料,接著透過 Reflection 動態地產生物件集合,但是物件的 Property Name 就遷就 ColumnName,一整個怪啊!
如果我們要練習 Reflection 的用法,這是個非常好的練習,但是要用在 Production 上我們還有 Dapper 可以選擇,搭配我接下來要介紹的三種自定義欄位對應方式,我相信怎樣都比自己寫 Reflection 來得好。
關於 Dapper 的用法,黑大的文章是必讀的,我就不贅述了。
首先我有這樣一個資料表,我拿這個資料表來當範例。
然後,我要把上頭的資料表對應成下面這個類別。
Dapper.FluentColumnMapping
Dapper.FluentColumnMapping 是我要介紹的第一種,這個用起來就非常簡單,提供的功能也很單純,就是做欄位的對應而已,話不多說,來看一下範例程式碼。
[TestMethod]
public void Test_FluentColumnMapping()
{
var columnMappings = new ColumnMappingCollection();
columnMappings.RegisterType<Product>()
.MapProperty(x => x.Id).ToColumn("MyId")
.MapProperty(x => x.Name).ToColumn("MyName")
.MapProperty(x => x.Price).ToColumn("Num_Price");
columnMappings.RegisterWithDapper();
IEnumerable<Product> products;
using (SqlConnection sql = new SqlConnection(connectionString))
{
products = sql.Query<Product>(@"SELECT * FROM TestTable");
}
Assert.AreEqual("無線網路分享器", products.Single().Name);
}
使用上,資料型態一定要注意一下,至少邏輯上要可以轉型轉得過去,舉個例子,資料庫內的資料型態是 nvarchar(50),資料內容是 2016/01/01 00:00:00
,那麼 Property 的資料型別可以是 DateTime,工具會自動幫你轉型,但不要來個資料內容是 我死硬要轉
,硬要轉成 DateTime,那就是來亂的。
Dapper.FluentMap
第二個要介紹的是 Dapper.FluentMap,這個工具要多做一件事情,要先產生一個繼承自 EntityMap<T>
類別,用來定義欄位對應的規則。
public class ProductMap : EntityMap<Product>
{
public ProductMap()
{
Map(x => x.Id).ToColumn("myid", false);
Map(x => x.Name).ToColumn("MyName");
Map(x => x.Price).ToColumn("Num_Price");
}
}
ToColumn()
方法中把 caseSensitive
參數設為 false 就可以不管欄位名稱的大小寫,接著初始化之後就可以了,我們看下面使用範例。
[TestMethod]
public void Test_FluentMap()
{
FluentMapper.Initialize(cfg =>
{
cfg.AddMap(new ProductMap());
});
IEnumerable<Product> products;
using (SqlConnection sql = new SqlConnection(connectionString))
{
products = sql.Query<Product>(@"SELECT * FROM TestTable");
}
Assert.AreEqual("無線網路分享器", products.Single().Name);
}
這個工具也會像前面一個工具一樣自動幫忙轉型,雖然操作上較為繁瑣,但是它可以提供像是 Convetion Mapping、Transformation 的功能,搭配 Dommel 套件還可以做簡單的 CRUD,詳情就參考作者在 GitHub 上的說明。
實作 SqlMapper.ITypeMap
如果你覺得使用別人做好的工具,是看輕您的程式撰寫功力,Dapper 裡面有一個介面 SqlMapper.ITypeMap,您可以實作它,國外也有神人幫您弄好了 kalebpederson/ColumnAttributeTypeMapper.cs,使用這種方式需要搭配 ColumnAttribute
,怎麼搭配請看下面。
public class Product
{
[Column("MyId")]
public int Id { get; set; }
[Column("MyName")]
public DateTime Name { get; set; }
[Column("Num_Price")]
public int Price { get; set; }
public string Memo { get; set; }
}
接著呼叫 SqlMapper.SetTypeMap
把要對應的類別跟欄位映射丟進去就可以了。
[TestMethod]
public void TestMethod1()
{
Dapper.SqlMapper.SetTypeMap(
typeof(Product),
new ColumnAttributeTypeMapper<Product>());
IEnumerable<Product> products;
using (SqlConnection sql = new SqlConnection(connectionString))
{
products = sql.Query<Product>(@"SELECT * FROM TestTable");
}
Assert.AreEqual("無線網路分享器", products.Single().Name);
}
這種做法一樣會自動幫忙轉型,以上就 Dapper 可以支援的三種自定義欄位的方式做個介紹,善用工具可以事半功倍,這個「功」倍不只是撰寫 Production Code 當下的功,也有後續維護的功。
< Source Code >