有個案子使用 ASP.NET Core 2.1 建立 API 撈取 MySQL 資料,使用 "Pomelo.EntityFrameworkCore.MySql" 套件,操作和預設的 EntityFramework Core 一樣。
現在有一案例,客戶提供 MySQL statement 要撈取想要的資料,statement 中有 "UNION ALL",我試著轉成 Linq ,"UNION ALL" 的部分使用 "IQueryable<T>.Contact(IQueryable<T>)",在執行時發生錯誤,如果改為 "IEnumerable<T>.Contact(IEnumerable<T>)" 則可正常執行,估計這套件無法將 "IQueryable<T>.Contact(IQueryable<T>)" 轉換成正確的 MySQL statement "UNION ALL",考慮到效能所以不使用"IEnumerable<T>.Contact(IEnumerable<T>)",因此決定使用 raw SQL
var result = new List<MyReportViewModel>(); var ym = $"{model.Year}-{(model.Month < 10 ? "0" : "")}{model.Month}"; using (var command = _context.Database.GetDbConnection().CreateCommand()) { command.CommandText = $@" SELECT * FROM ( {GenerateJasperMySql(ym)} UNION ALL {GenerateJasperMySql(ym, "STATEHISTORY")} )AS SOURCE ORDER BY object_name, start_time ASC "; _context.Database.OpenConnection(); using (var reader = command.ExecuteReader()) { if (reader.HasRows) { while (reader.Read()) { result.Add(new MyReportViewModel { object_type = (string)reader["object_type"], object_id = reader.GetInt32(1), object_name = (string)reader["object_name"], object_service = (string)reader["object_service"], start_time = (string)reader["start_time"], end_time = (string)reader["end_time"], object_state = (string)reader["object_state"], output = (string)reader["output"], }); } } } } return result;
備註:
_context : 依賴注入的 DbContext
GenerateJasperMySql() : 因為 "UNION ALL" 的兩個 SQL statement 類似,因此設計這個 method 來產生
參考 使用 DataReader 擷取資料