查詢範例
This commit is contained in:
246
web/App_Code/api/pivot01Controller.cs
Normal file
246
web/App_Code/api/pivot01Controller.cs
Normal file
@@ -0,0 +1,246 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Web.Http;
|
||||
using System.Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// pivot01Controller - 法會報名統計分析 API
|
||||
/// 設計理念:直接查詢 SQL VIEW,保持彈性與簡潔
|
||||
/// </summary>
|
||||
[ezAuthorize]
|
||||
public class pivot01Controller : ApiController
|
||||
{
|
||||
// 連線字串
|
||||
private readonly string _connectionString;
|
||||
|
||||
public pivot01Controller()
|
||||
{
|
||||
// 優先使用 shopConn 連線字串(純 SQL Server 連線字串)
|
||||
var shopConnectionString = ConfigurationManager.ConnectionStrings["shopConn"]?.ConnectionString;
|
||||
if (!string.IsNullOrEmpty(shopConnectionString))
|
||||
{
|
||||
// 移除不相容的 Provider 參數
|
||||
_connectionString = shopConnectionString.Replace("Provider=SQLOLEDB;", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 備用方案:從 Entity Framework 連線字串中提取 SQL Server 連線字串
|
||||
var efConnectionString = ConfigurationManager.ConnectionStrings["ezEntities"]?.ConnectionString;
|
||||
if (!string.IsNullOrEmpty(efConnectionString))
|
||||
{
|
||||
// 解析 EF 連線字串,提取 provider connection string 部分
|
||||
var startIndex = efConnectionString.IndexOf("provider connection string="") + "provider connection string="".Length;
|
||||
var endIndex = efConnectionString.LastIndexOf(""");
|
||||
if (startIndex > 0 && endIndex > startIndex)
|
||||
{
|
||||
_connectionString = efConnectionString.Substring(startIndex, endIndex - startIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("無法解析 Entity Framework 連線字串");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("找不到可用的資料庫連線字串");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region 通用 VIEW 查詢方法
|
||||
|
||||
/// <summary>
|
||||
/// 執行 SQL 查詢並回傳 DataTable
|
||||
/// </summary>
|
||||
/// <param name="sql">SQL 查詢語句</param>
|
||||
/// <param name="parameters">參數陣列</param>
|
||||
/// <returns>查詢結果 DataTable</returns>
|
||||
private DataTable ExecuteSqlQuery(string sql, SqlParameter[] parameters = null)
|
||||
{
|
||||
var dataTable = new DataTable();
|
||||
|
||||
try
|
||||
{
|
||||
using (var connection = new SqlConnection(_connectionString))
|
||||
using (var command = new SqlCommand(sql, connection))
|
||||
{
|
||||
// 設定逾時時間為 60 秒
|
||||
command.CommandTimeout = 60;
|
||||
|
||||
// 加入參數
|
||||
if (parameters != null && parameters.Length > 0)
|
||||
{
|
||||
command.Parameters.AddRange(parameters);
|
||||
}
|
||||
|
||||
// 開啟連線並執行查詢
|
||||
connection.Open();
|
||||
using (var adapter = new SqlDataAdapter(command))
|
||||
{
|
||||
adapter.Fill(dataTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
throw new Exception($"SQL 查詢錯誤: {ex.Message}", ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"執行查詢時發生錯誤: {ex.Message}", ex);
|
||||
}
|
||||
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DataTable 轉換為動態物件列表(保留中文欄位名)
|
||||
/// </summary>
|
||||
/// <param name="dt">DataTable</param>
|
||||
/// <returns>Dictionary 列表</returns>
|
||||
private List<Dictionary<string, object>> DataTableToDictionary(DataTable dt)
|
||||
{
|
||||
var list = new List<Dictionary<string, object>>();
|
||||
|
||||
foreach (DataRow row in dt.Rows)
|
||||
{
|
||||
var dict = new Dictionary<string, object>();
|
||||
foreach (DataColumn col in dt.Columns)
|
||||
{
|
||||
// 保留原始欄位名稱(包含中文)
|
||||
dict[col.ColumnName] = row[col] == DBNull.Value ? null : row[col];
|
||||
}
|
||||
list.Add(dict);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region API 端點
|
||||
|
||||
/// <summary>
|
||||
/// GET /api/pivot01/activity_stats
|
||||
/// 查詢法會統計(對應「法會統計」VIEW)
|
||||
/// </summary>
|
||||
/// <param name="year">查詢年份</param>
|
||||
/// <returns>法會統計資料</returns>
|
||||
[HttpGet]
|
||||
[Route("api/pivot01/activity_stats")]
|
||||
public IHttpActionResult GetActivityStats(int year)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 驗證年份參數
|
||||
if (year < 1900 || year > 2100)
|
||||
{
|
||||
return BadRequest("年份參數不正確,請輸入 1900 ~ 2100 之間的年份");
|
||||
}
|
||||
|
||||
// 建立 SQL 查詢(包含當年度及無日期的法會)
|
||||
string sql = @"
|
||||
SELECT * FROM [法會統計]
|
||||
WHERE (YEAR(開始日期) = @year OR 開始日期 IS NULL)
|
||||
ORDER BY
|
||||
CASE WHEN 開始日期 IS NULL THEN 1 ELSE 0 END,
|
||||
開始日期 DESC,
|
||||
結束日期 DESC
|
||||
";
|
||||
|
||||
// 建立參數
|
||||
var parameters = new[]
|
||||
{
|
||||
new SqlParameter("@year", SqlDbType.Int) { Value = year }
|
||||
};
|
||||
|
||||
// 執行查詢
|
||||
var dataTable = ExecuteSqlQuery(sql, parameters);
|
||||
var data = DataTableToDictionary(dataTable);
|
||||
|
||||
// 回應結果
|
||||
var result = new
|
||||
{
|
||||
success = true,
|
||||
data = data,
|
||||
message = "查詢成功",
|
||||
rowCount = data.Count
|
||||
};
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorResponse = new
|
||||
{
|
||||
success = false,
|
||||
message = $"查詢失敗:{ex.Message}",
|
||||
error = ex.ToString()
|
||||
};
|
||||
return Content(System.Net.HttpStatusCode.BadRequest, errorResponse);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GET /api/pivot01/registration_details
|
||||
/// 查詢報名明細(對應「報名明細查詢」VIEW)
|
||||
/// </summary>
|
||||
/// <param name="activityNum">法會編號(必填)</param>
|
||||
/// <returns>報名明細資料</returns>
|
||||
[HttpGet]
|
||||
[Route("api/pivot01/registration_details")]
|
||||
public IHttpActionResult GetRegistrationDetails(int? activityNum = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 驗證參數
|
||||
if (!activityNum.HasValue || activityNum.Value <= 0)
|
||||
{
|
||||
return BadRequest("請提供有效的法會編號(activityNum)");
|
||||
}
|
||||
|
||||
// 建立查詢 SQL
|
||||
string sql = @"
|
||||
SELECT * FROM [報名明細查詢]
|
||||
WHERE 法會ID = @activityNum
|
||||
ORDER BY 報名日期 DESC, 報名編號 DESC
|
||||
";
|
||||
|
||||
// 建立參數
|
||||
var parameters = new[]
|
||||
{
|
||||
new SqlParameter("@activityNum", SqlDbType.Int) { Value = activityNum.Value }
|
||||
};
|
||||
|
||||
// 執行查詢
|
||||
var dataTable = ExecuteSqlQuery(sql, parameters);
|
||||
var data = DataTableToDictionary(dataTable);
|
||||
|
||||
// 回應結果
|
||||
var result = new
|
||||
{
|
||||
success = true,
|
||||
data = data,
|
||||
message = "查詢成功",
|
||||
rowCount = data.Count
|
||||
};
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorResponse = new
|
||||
{
|
||||
success = false,
|
||||
message = $"查詢失敗:{ex.Message}",
|
||||
error = ex.ToString()
|
||||
};
|
||||
return Content(System.Net.HttpStatusCode.BadRequest, errorResponse);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user