2013年5月13日 星期一

如何使用Json.Net轉換舊版本的DataSet中DataRow

好好好,我知道現在流行的是Entity Framework - Code First ,很屌,屌爆了(半夜出BUG屌就真的得爆了?)。不過總是有些老Code還得維護,在這些Code上西天之前,搞不好還得先上個雲端,是吧?不雲端一下老東西還賣的出去嗎?老頭子們都陣亡了,難道要小鬼們重新寫這些糾結到纏綿斐撤的Code?

好,想當年ORM的一哥,xxxxDataSet.xsd也曾在江湖上飭剎風雲,今天老闆要你把它上雲端,你上不上?還好現在都很人性的,隨便拿個Json序列化一下就能交差了事,應該是這樣的吧。大概就是先這樣這樣,在那樣那樣....

            var ds = new Database1DataSet();
            var table = ds.DataTable1;
            string json = JsonConvert.SerializeObject(table.Rows);    

打完收工!,先來Run一下,果然很快就ok啦,這時候拿複雜一點有關連的資料表,且資料庫裡面已經有資料的系統來Run一下,咦?怎麼卡住了!???

其實是因為Typed DataSet自動產生的DataRow包含了太多不必要的連結跟參考,但是那些DataRow類別是自動產生的,並不適合直接修改。其實這時候有另外一種方式,直接看Code比較快
//這行當然是寫在某個函式中,這邊簡化讓他空中飄吧
string json = JsonConvert.SerializeObject(table.Rows, new JsonSerializerSettings()
            {
                ContractResolver = new DynamicContractResolver(),                       
            });


public class DynamicContractResolver : DefaultContractResolver
{
    protected override IList< JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList< JsonProperty> properties = base.CreateProperties(type, memberSerialization);

        var ignoreProperties = new string[] { "ItemArray", "Table", "RowState", "RowError", "HasErrors" };
                
        properties =
            properties.Where(p => !p.PropertyName.EndsWith("Row") && !ignoreProperties.Contains(p.PropertyName)).ToList();

        //這邊可以自行在略過一些不必序列的資料條件,這邊範例是結尾為Date的欄位也不要序列化
        properties = properties.Where(o => !o.PropertyName.EndsWith("Date")).ToList();

        return properties;
    }
}
這麼一來就可以略過DataRow中不必要的屬性,老DataRow也能上天堂啦

順道一提,如果DataRow轉換上會產生Exception,可以這樣處理
                return JsonConvert.SerializeObject(table.Rows, new JsonSerializerSettings()
                    {
                        ContractResolver = new DynamicContractResolver(tableName),
                        Error = (object o, ErrorEventArgs e) =>
                        {
                            //這邊放錯誤處理函式
                            e.ErrorContext.Handled = true;
                        }
                    });
不過如果有大量錯誤,將會造成序列化非常非常非常的慢哦,最好用別種方式解決

沒有留言:

張貼留言