[C#.NET] 動態產生 AS400 對應的 POCO/DTO

手動建立 OR-M 的 POCO 可是一件苦差事,針對 EF 不支援的資料庫,透過這個小技巧,可以大大提升程式設計師的生產力、降低錯誤發生,團隊使用 EF開發資料庫,但 AS400 並沒有支援 EF的 Provider,怎麼辦,我再也不會回頭使用弱型別的 DataTable 了,這時候 Dapper 就派上用場,請參考:https://www.dotblogs.com.tw/yc421206/2015/04/20/as400_connect_provider

使用 ORM 的要先準備好POCO ,欄位只要一多,手動建立 POCO 多累人阿,本來想自幹 Parser 產生 POCO,還好,自幹之前找到了 Kevin 的 BLog:http://kevintsengtw.blogspot.tw/2015/10/dapper-linqpad-sql-command.html,Kevin 有你真好

重點就是以下的擴充方法,以下代碼節錄 Kevin 的 BLog:

public static class LINQPadExtensions
{
	private static readonly Dictionary<Type, string> TypeAliases = new Dictionary<Type, string>()
	{
		{ typeof(int), "int" },
		{ typeof(short), "short" },
		{ typeof(byte), "byte" },
		{ typeof(byte[]), "byte[]" },
		{ typeof(long), "long" },
		{ typeof(double), "double" },
		{ typeof(decimal), "decimal" },
		{ typeof(float), "float" },
		{ typeof(bool), "bool" },
		{ typeof(string), "string" }
	};

	private static readonly HashSet<Type> NullableTypes = new HashSet<Type>()
	{
		typeof(int),
		typeof(short),
		typeof(long),
		typeof(double),
		typeof(decimal),
		typeof(float),
		typeof(bool),
		typeof(DateTime)
	};

	public static string DumpClass(this IDbConnection connection, string sql, string className = "Info")
	{
		if (connection.State != ConnectionState.Open)
		{
			connection.Open();
		}

		var cmd = connection.CreateCommand();
		cmd.CommandText = sql;
		var reader = cmd.ExecuteReader();
		var builder = new StringBuilder();

		do
		{
			if (reader.FieldCount <= 1) { continue; }
			builder.AppendFormat("public class {0}{1}", className, Environment.NewLine);
			builder.AppendLine("{");
			var schema = reader.GetSchemaTable();
			foreach (DataRow row in schema.Rows)
			{
				var type = (Type)row["DataType"];
				var name = TypeAliases.ContainsKey(type) ? TypeAliases[type] : type.Name;
				var isNullable = (bool)row["AllowDBNull"] && NullableTypes.Contains(type);
				var collumnName = (string)row["ColumnName"];
				builder.AppendLine(string.Format("\tpublic {0}{1} {2} {{ get; set; }}", name, isNullable ? "?" : string.Empty, collumnName));

				builder.AppendLine();
			}

			builder.AppendLine("}");
			builder.AppendLine();
		} while (reader.NextResult());

		return builder.ToString();
	}
}
上述程式碼,不是只能在LINQPad上執行

上面的程式碼邏輯很簡單,就是透過 Select 語法把 Table 欄位找過一遍並依照 Table 欄位產生類別欄位,利用 LINQPad Dump() 呈現結果,最後把類別複製到專案就可以用了

當然,這並非是一個最完美的作法,還有很大的空間可以改善,對我而言就很夠用了;

平時有用 LINQPad 來處理輸出結果的人,應該都很享受 LINQPad Dump() 的功能,本人是很喜愛這功能的,還沒體驗過LINQPad的夥伴,趕緊加入吧。

這個擴充方法是針對 IDbConnection 型別進行擴充 (Dapper 也是如此),也就是說所有實作 IDbConnection 的衍生類別都能享有這功能,當不能用 EF 產生 POCO/DTO 時,這個擴充方法就是一個相當好用的小技巧。

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo