修正多處 LINQ-to-Entities 查詢,避免 Nullable .Contains()、.ToString()、Request[] 直接使用造成翻譯失敗。
API 查詢同步改寫 .Contains()、.OrderBy()、複雜 GroupBy/Math.Round,必要時 materialize 或加 HasValue。 Participation rate / kind breakdown 改在記憶體計算,同時檢查整數陣列 .Contains() 的型別安全性。
This commit is contained in:
@@ -319,6 +319,8 @@ public class pivotController : ApiController
|
||||
total_followers = g.Select(x => x.FollowerNum).Distinct().Count(),
|
||||
total_amount = g.Sum(x => x.Amount),
|
||||
total_qty = g.Sum(x => x.Qty),
|
||||
// ⚠️ 複雜聚合:巢狀 GroupBy → Average → Sum,EF 6.4.4 可轉換
|
||||
// 如遇到 NotSupportedException,改為在 .ToList() 後計算
|
||||
avg_amount_per_follower = g.GroupBy(x => x.FollowerNum).Average(fg => fg.Sum(x => x.Amount))
|
||||
})
|
||||
.OrderByDescending(x => x.start_date)
|
||||
@@ -391,6 +393,9 @@ public class pivotController : ApiController
|
||||
query = query.Where(x => x.FollowerNum == followerNum.Value);
|
||||
}
|
||||
|
||||
// ✅ 優化:先取得總活動數,避免在投影中跨表查詢
|
||||
var totalActivitiesCount = _db.activities.Count();
|
||||
|
||||
// 信眾統計分析
|
||||
var followerStats = query.GroupBy(x => new { x.FollowerNum, x.FollowerName, x.FollowerCode })
|
||||
.Select(g => new
|
||||
@@ -401,9 +406,10 @@ public class pivotController : ApiController
|
||||
total_activities = g.Select(x => x.ActivityNum).Distinct().Count(),
|
||||
total_amount = g.Sum(x => x.Amount),
|
||||
total_orders = g.Select(x => x.OrderDate).Count(),
|
||||
// ⚠️ 複雜聚合:巢狀 GroupBy → Average → Sum,EF 6.4.4 可轉換
|
||||
// 如遇到 NotSupportedException,改為在 .ToList() 後計算
|
||||
avg_amount_per_activity = g.GroupBy(x => x.ActivityNum).Average(ag => ag.Sum(x => x.Amount)),
|
||||
is_patron_count = g.Count(x => x.HasParent),
|
||||
participation_rate = Math.Round((double)g.Select(x => x.ActivityNum).Distinct().Count() / _db.activities.Count() * 100, 2),
|
||||
favorite_kinds = g.GroupBy(x => x.KindName)
|
||||
.OrderByDescending(kg => kg.Sum(x => x.Amount))
|
||||
.Take(3)
|
||||
@@ -419,6 +425,22 @@ public class pivotController : ApiController
|
||||
.ToList()
|
||||
})
|
||||
.OrderByDescending(x => x.total_amount)
|
||||
.ToList()
|
||||
// ✅ 優化:在記憶體中計算 participation_rate,避免 Math.Round 在 LINQ to Entities 投影中
|
||||
.Select(x => new
|
||||
{
|
||||
x.follower_num,
|
||||
x.follower_name,
|
||||
x.follower_code,
|
||||
x.total_activities,
|
||||
x.total_amount,
|
||||
x.total_orders,
|
||||
x.avg_amount_per_activity,
|
||||
x.is_patron_count,
|
||||
participation_rate = Math.Round((double)x.total_activities / totalActivitiesCount * 100, 2),
|
||||
x.favorite_kinds,
|
||||
x.recent_activities
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var result = new
|
||||
@@ -527,35 +549,31 @@ public class pivotController : ApiController
|
||||
break;
|
||||
|
||||
case "activity":
|
||||
stats = query.GroupBy(x => new { x.ActivityNum, x.ActivityName, x.StartDate })
|
||||
// ✅ 優化:一次性取出所有資料,避免 N+1 查詢
|
||||
var activityData = query.ToList();
|
||||
|
||||
stats = activityData.GroupBy(x => new { x.ActivityNum, x.ActivityName, x.StartDate })
|
||||
.Select(g => new
|
||||
{
|
||||
activity_num = g.Key.ActivityNum,
|
||||
activity_name = g.Key.ActivityName,
|
||||
start_date = g.Key.StartDate,
|
||||
total_amount = g.Sum(x => x.Amount)
|
||||
total_amount = g.Sum(x => x.Amount),
|
||||
// ✅ 優化:在記憶體中分組,避免子查詢
|
||||
kind_breakdown = g.GroupBy(x => x.KindName)
|
||||
.Select(kg => new
|
||||
{
|
||||
kind = kg.Key,
|
||||
amount = kg.Sum(x => x.Amount),
|
||||
// ✅ 優化:在記憶體中計算百分比
|
||||
percentage = g.Sum(x => x.Amount) > 0
|
||||
? Math.Round((double)kg.Sum(x => x.Amount) / (double)g.Sum(x => x.Amount) * 100, 2)
|
||||
: 0
|
||||
})
|
||||
.OrderByDescending(x => x.amount)
|
||||
.ToList()
|
||||
})
|
||||
.OrderByDescending(x => x.start_date)
|
||||
.ToList()
|
||||
.Select(g => new
|
||||
{
|
||||
g.activity_num,
|
||||
g.activity_name,
|
||||
g.start_date,
|
||||
g.total_amount,
|
||||
kind_breakdown = query.Where(x => x.ActivityNum == g.activity_num)
|
||||
.GroupBy(x => x.KindName)
|
||||
.Select(kg => new
|
||||
{
|
||||
kind = kg.Key,
|
||||
amount = kg.Sum(x => x.Amount),
|
||||
percentage = g.total_amount.HasValue && g.total_amount.Value > 0
|
||||
? Math.Round((double)(kg.Sum(x => x.Amount) ?? 0) / (double)g.total_amount.Value * 100, 2)
|
||||
: 0
|
||||
})
|
||||
.OrderByDescending(x => x.amount)
|
||||
.ToList()
|
||||
})
|
||||
.ToList();
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user