Files
17168ERP/web/test_asenumerable_check.aspx.cs
2025-11-12 15:58:20 +08:00

347 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Text;
using System.Diagnostics;
using System.Linq;
using Model;
public partial class test_asenumerable_check : System.Web.UI.Page
{
private StringBuilder output = new StringBuilder();
private int passCount = 0;
private int failCount = 0;
private int warnCount = 0;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
litResult.Text = "<p style='color:#888;'>點擊「執行檢測」開始測試修改結果</p>";
}
}
protected void btnRunTest_Click(object sender, EventArgs e)
{
output.Clear();
passCount = 0;
failCount = 0;
warnCount = 0;
output.AppendLine("<div style='margin-bottom: 20px;'>");
output.AppendLine($"<p>測試時間: {DateTime.Now:yyyy-MM-dd HH:mm:ss}</p>");
output.AppendLine("</div>");
// 執行所有測試
TestAccountingKind();
TestActivityKind();
TestFollowers();
TestMembers();
TestOrders();
// 顯示總結
output.AppendLine("<hr />");
output.AppendLine("<h2>📊 測試總結</h2>");
output.AppendLine($"<p class='success'>✅ 通過: {passCount} 項</p>");
output.AppendLine($"<p class='error'>❌ 失敗: {failCount} 項</p>");
output.AppendLine($"<p class='warning'>⚠️ 警告: {warnCount} 項</p>");
if (failCount == 0)
{
output.AppendLine("<h3 class='success'>🎉 所有測試通過!修改成功!</h3>");
}
else
{
output.AppendLine("<h3 class='error'>⚠️ 發現問題,請檢查失敗的項目</h3>");
}
litResult.Text = output.ToString();
}
private void TestAccountingKind()
{
output.AppendLine("<h3>測試 1: accounting_kind 查詢優化</h3>");
using (var db = new ezEntities())
{
var sqlLog = new StringBuilder();
db.Database.Log = sql => sqlLog.AppendLine(sql);
try
{
// 測試 1.1: 單筆查詢
sqlLog.Clear();
var sw = Stopwatch.StartNew();
var result = db.accounting_kind.Where(q => q.num == 1).FirstOrDefault();
sw.Stop();
CheckQuery("單筆查詢 (Where + FirstOrDefault)",
sqlLog.ToString(),
sw.ElapsedMilliseconds,
shouldHaveWhere: true,
shouldHaveSelectAll: false,
maxTime: 50);
// 測試 1.2: 檢查子資料 (應該用 Any)
sqlLog.Clear();
sw.Restart();
var hasChildren = db.accounting_kind.Any(q => q.root == 1);
sw.Stop();
CheckQuery("檢查子資料存在 (Any)",
sqlLog.ToString(),
sw.ElapsedMilliseconds,
shouldHaveWhere: true,
shouldHaveExists: true,
maxTime: 30);
// 測試 1.3: 取得子資料清單
sqlLog.Clear();
sw.Restart();
var children = db.accounting_kind.Where(q => q.root == 1).ToList();
sw.Stop();
CheckQuery("取得子資料清單 (Where + ToList)",
sqlLog.ToString(),
sw.ElapsedMilliseconds,
shouldHaveWhere: true,
shouldHaveSelectAll: false,
maxTime: 100);
}
catch (Exception ex)
{
LogError($"accounting_kind 測試失敗: {ex.Message}");
}
}
}
private void TestActivityKind()
{
output.AppendLine("<h3>測試 2: activity_kind 查詢優化</h3>");
using (var db = new ezEntities())
{
var sqlLog = new StringBuilder();
db.Database.Log = sql => sqlLog.AppendLine(sql);
try
{
// 單筆查詢 + 排序
sqlLog.Clear();
var sw = Stopwatch.StartNew();
var result = db.activity_kind
.Where(q => q.num == 1)
.OrderBy(q => q.kind)
.FirstOrDefault();
sw.Stop();
CheckQuery("單筆查詢 + 排序 (Where + OrderBy + FirstOrDefault)",
sqlLog.ToString(),
sw.ElapsedMilliseconds,
shouldHaveWhere: true,
shouldHaveOrderBy: true,
maxTime: 50);
}
catch (Exception ex)
{
LogError($"activity_kind 測試失敗: {ex.Message}");
}
}
}
private void TestFollowers()
{
output.AppendLine("<h3>測試 3: followers 查詢優化</h3>");
using (var db = new ezEntities())
{
var sqlLog = new StringBuilder();
db.Database.Log = sql => sqlLog.AppendLine(sql);
try
{
// 測試字串查詢 (Contains)
sqlLog.Clear();
var sw = Stopwatch.StartNew();
var result = db.followers
.Where(q => q.f_number.Contains("A"))
.Take(10)
.ToList();
sw.Stop();
CheckQuery("字串查詢 (Contains)",
sqlLog.ToString(),
sw.ElapsedMilliseconds,
shouldHaveWhere: true,
shouldHaveLike: true,
maxTime: 100);
}
catch (Exception ex)
{
LogError($"followers 測試失敗: {ex.Message}");
}
}
}
private void TestMembers()
{
output.AppendLine("<h3>測試 4: members 查詢優化</h3>");
using (var db = new ezEntities())
{
var sqlLog = new StringBuilder();
db.Database.Log = sql => sqlLog.AppendLine(sql);
try
{
// 測試批次查詢
var ids = new[] { 1, 2, 3 };
sqlLog.Clear();
var sw = Stopwatch.StartNew();
var result = db.members.Where(q => ids.Contains(q.num)).ToList();
sw.Stop();
CheckQuery("批次 ID 查詢 (Contains)",
sqlLog.ToString(),
sw.ElapsedMilliseconds,
shouldHaveWhere: true,
shouldHaveIn: true,
maxTime: 100);
}
catch (Exception ex)
{
LogError($"members 測試失敗: {ex.Message}");
}
}
}
private void TestOrders()
{
output.AppendLine("<h3>測試 5: pro_order_detail 聚合查詢</h3>");
using (var db = new ezEntities())
{
var sqlLog = new StringBuilder();
db.Database.Log = sql => sqlLog.AppendLine(sql);
try
{
// 測試 Count
sqlLog.Clear();
var sw = Stopwatch.StartNew();
var count = db.pro_order_detail.Count(q => q.num > 0);
sw.Stop();
CheckQuery("Count 查詢",
sqlLog.ToString(),
sw.ElapsedMilliseconds,
shouldHaveWhere: true,
shouldHaveCount: true,
maxTime: 50);
}
catch (Exception ex)
{
LogError($"pro_order_detail 測試失敗: {ex.Message}");
}
}
}
private void CheckQuery(string testName, string sql, long milliseconds,
bool shouldHaveWhere = false,
bool shouldHaveSelectAll = false,
bool shouldHaveExists = false,
bool shouldHaveOrderBy = false,
bool shouldHaveLike = false,
bool shouldHaveIn = false,
bool shouldHaveCount = false,
long maxTime = 100)
{
output.AppendLine("<div class='test-item'>");
output.AppendLine($"<h4>🔸 {testName}</h4>");
output.AppendLine($"<p>執行時間: {milliseconds}ms</p>");
bool passed = true;
var issues = new StringBuilder();
// 檢查是否有 WHERE 條件
if (shouldHaveWhere && !sql.Contains("WHERE"))
{
issues.AppendLine("❌ 缺少 WHERE 條件(可能載入整表)<br/>");
passed = false;
}
// 檢查是否有不當的 SELECT *
if (!shouldHaveSelectAll && sql.Contains("SELECT") && !sql.Contains("WHERE") && !sql.Contains("TOP"))
{
issues.AppendLine("❌ SELECT 沒有條件限制(載入整表)<br/>");
passed = false;
}
// 檢查是否使用 EXISTSAny 應該產生)
if (shouldHaveExists && !sql.Contains("EXISTS"))
{
issues.AppendLine("⚠️ 建議使用 EXISTS 而非載入資料<br/>");
warnCount++;
}
// 檢查是否有 ORDER BY
if (shouldHaveOrderBy && !sql.Contains("ORDER BY"))
{
issues.AppendLine("❌ 缺少 ORDER BY排序應該在資料庫執行<br/>");
passed = false;
}
// 檢查是否有 LIKEContains 應該產生)
if (shouldHaveLike && !sql.Contains("LIKE"))
{
issues.AppendLine("❌ 字串查詢未轉為 LIKE<br/>");
passed = false;
}
// 檢查是否有 IN批次查詢應該產生
if (shouldHaveIn && !sql.Contains("IN"))
{
issues.AppendLine("❌ 批次查詢未轉為 IN<br/>");
passed = false;
}
// 檢查是否有 COUNT聚合函數應該在資料庫執行
if (shouldHaveCount && !sql.Contains("COUNT"))
{
issues.AppendLine("❌ COUNT 未在資料庫執行<br/>");
passed = false;
}
// 檢查執行時間
if (milliseconds > maxTime)
{
issues.AppendLine($"⚠️ 執行時間較長 (>{maxTime}ms),可能仍有優化空間<br/>");
warnCount++;
}
if (passed)
{
output.AppendLine("<p class='success'>✅ 測試通過</p>");
passCount++;
}
else
{
output.AppendLine("<p class='error'>❌ 測試失敗</p>");
output.AppendLine($"<div style='color:#f48771;'>{issues}</div>");
failCount++;
}
// 顯示 SQL
output.AppendLine("<div class='sql-box'>");
output.AppendLine("<strong>產生的 SQL:</strong><br/>");
output.AppendLine($"<pre>{System.Web.HttpUtility.HtmlEncode(sql)}</pre>");
output.AppendLine("</div>");
output.AppendLine("</div>");
}
private void LogError(string message)
{
output.AppendLine($"<p class='error'>❌ {message}</p>");
failCount++;
}
}