更新查詢方式

This commit is contained in:
2025-11-12 15:58:20 +08:00
parent 6f5a2e65bd
commit 5ae262205c
17 changed files with 501 additions and 130 deletions

View File

@@ -0,0 +1,346 @@
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++;
}
}