C# Entity Framework Zero Downtime Deployment
C# Entity Framework Zero Downtime Deployment คืออะไร

Entity Framework (EF) Core เป็น ORM (Object-Relational Mapper) หลักของ .NET ที่ช่วย developers ทำงานกับ database ผ่าน C# objects แทนการเขียน SQL โดยตรง Zero Downtime Deployment คือการ deploy application version ใหม่โดยไม่มี downtime — ผู้ใช้ไม่รู้สึกว่าระบบหยุดทำงาน ความท้าทายหลักคือ database migrations ที่ต้อง backward compatible เพราะระหว่าง deploy มีทั้ง version เก่าและใหม่ทำงานพร้อมกัน บทความนี้อธิบายวิธี deploy EF Core applications แบบ zero downtime พร้อมตัวอย่าง code
Zero Downtime Deployment Strategies
# zdt_strategies.py — Zero downtime deployment strategies
import json
class ZDTStrategies:
STRATEGIES = {
"rolling": {
"name": "Rolling Deployment",
"description": "Deploy ทีละ instance — old + new versions run พร้อมกัน",
"requirement": "Database schema ต้อง compatible กับทั้ง 2 versions",
"tools": "Kubernetes rolling update, Azure App Service slots",
},
"blue_green": {
"name": "Blue-Green Deployment",
"description": "Deploy version ใหม่ (Green) แยก → switch traffic → retire Blue",
"requirement": "Database shared ระหว่าง Blue + Green → migration ต้อง backward compatible",
"tools": "Kubernetes services, AWS ALB, Azure Traffic Manager",
},
"canary": {
"name": "Canary Deployment",
"description": "ส่ง traffic 5-10% ไป version ใหม่ → monitor → ค่อยเพิ่ม",
"requirement": "เหมือน Rolling — schema ต้อง compatible",
"tools": "Istio, Flagger, AWS App Mesh",
},
}
CHALLENGES = {
"schema_change": "Schema changes (add/remove columns) ต้อง backward compatible",
"data_migration": "Data migration ต้องไม่ lock tables นาน",
"rollback": "ต้อง rollback ได้ถ้า version ใหม่มีปัญหา",
"connection_pool": "Connection pool ต้องไม่ขาด ระหว่าง deploy",
"ef_migration": "EF Migrations ต้อง idempotent + backward compatible",
}
def show_strategies(self):
print("=== ZDT Strategies ===\n")
for key, strat in self.STRATEGIES.items():
print(f"[{strat['name']}]")
print(f" {strat['description']}")
print(f" Requirement: {strat['requirement']}")
print()
def show_challenges(self):
print("=== Challenges ===")
for key, challenge in self.CHALLENGES.items():
print(f" [{key}] {challenge}")
zdt = ZDTStrategies()
zdt.show_strategies()
zdt.show_challenges()
EF Core Migration Best Practices
# ef_migrations.py — EF Core migration patterns for ZDT import json class EFMigrationPatterns: SAFE_OPERATIONS = """ // === SAFE Operations (backward compatible) === // 1. ADD column (nullable or with default) migrationBuilder.AddColumn( name: "MiddleName", table: "Users", type: "nvarchar(100)", nullable: true); // nullable = safe // 2. ADD table migrationBuilder.CreateTable( name: "UserPreferences", columns: table => new { Id = table.ColumnExpand-Contract Pattern

Python Migration Validator
# validator.py — Validate EF migrations for ZDT safety
import json
class MigrationValidator:
CODE = """
# ef_migration_validator.py — Check if migrations are ZDT-safe
import re
import json
from pathlib import Path
class MigrationSafetyChecker:
UNSAFE_PATTERNS = {
'DropColumn': {
'pattern': r'migrationBuilder\\.DropColumn',
'severity': 'critical',
'message': 'DROP COLUMN breaks old app versions reading this column',
'fix': 'Use expand-contract: add new column → migrate → drop old',
},
'RenameColumn': {
'pattern': r'migrationBuilder\\.RenameColumn',
'severity': 'critical',
'message': 'RENAME COLUMN breaks old app versions',
'fix': 'Use expand-contract: add new → copy data → drop old',
},
'DropTable': {
'pattern': r'migrationBuilder\\.DropTable',
'severity': 'high',
'message': 'DROP TABLE may break old app versions',
'fix': 'Only drop after all app versions stop using this table',
},
'AlterColumn_NotNull': {
'pattern': r'nullable:\\s*false',
'severity': 'high',
'message': 'Adding NOT NULL constraint may fail for existing rows',
'fix': 'Add with default value or make nullable first',
},
'RenameTable': {
'pattern': r'migrationBuilder\\.RenameTable',
'severity': 'critical',
'message': 'RENAME TABLE breaks old app versions',
'fix': 'Create new table → migrate data → drop old',
},
}
def check_file(self, filepath):
'''Check a single migration file for unsafe patterns'''
content = Path(filepath).read_text()
issues = []
for name, rule in self.UNSAFE_PATTERNS.items():
matches = re.findall(rule['pattern'], content)
if matches:
issues.append({
'rule': name,
'severity': rule['severity'],
'message': rule['message'],
'fix': rule['fix'],
'occurrences': len(matches),
})
return {
'file': str(filepath),
'safe': len(issues) == 0,
'issues': issues,
}
def check_directory(self, migrations_dir):
'''Check all migration files in directory'''
results = []
for f in sorted(Path(migrations_dir).glob('*.cs')):
if 'Designer' not in f.name:
results.append(self.check_file(f))
total = len(results)
safe = sum(1 for r in results if r['safe'])
unsafe = total - safe
return {
'total_migrations': total,
'safe': safe,
'unsafe': unsafe,
'details': [r for r in results if not r['safe']],
}
# checker = MigrationSafetyChecker()
# result = checker.check_directory("./Migrations")
# print(json.dumps(result, indent=2))
"""
def show_code(self):
print("=== Migration Validator ===")
print(self.CODE[:600])
validator = MigrationValidator()
validator.show_code()
CI/CD Pipeline
# cicd.py — CI/CD pipeline for ZDT with EF Core
import json
class ZDTPipeline:
GITHUB_ACTIONS = """
# .github/workflows/deploy-zdt.yml
name: Zero Downtime Deploy
on:
push:
branches: [main]
jobs:
validate-migrations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0'
- name: Check Migration Safety
run: |
python scripts/check_migrations.py ./src/Migrations
if [ $? -ne 0 ]; then
echo "UNSAFE migrations detected!"
exit 1
fi
- name: Run Tests
run: dotnet test --configuration Release
deploy:
needs: validate-migrations
runs-on: ubuntu-latest
steps:
- name: Apply Migrations
run: |
dotnet ef database update \\
--connection "}" \\
--project src/MyApp
- name: Rolling Deploy
run: |
kubectl set image deployment/myapp \\
myapp=myapp:} \\
--record
kubectl rollout status deployment/myapp \\
--timeout=300s
- name: Smoke Test
run: |
curl -f https://myapp.example.com/health || exit 1
- name: Rollback on Failure
if: failure()
run: |
kubectl rollout undo deployment/myapp
"""
DEPLOY_ORDER = [
"1. Validate: Check migration safety (no unsafe patterns)",
"2. Test: Run unit + integration tests with new schema",
"3. Migrate: Apply DB migrations (backward compatible)",
"4. Deploy: Rolling update — old + new run together",
"5. Verify: Health checks + smoke tests",
"6. Monitor: Watch error rates, latency for 15 min",
"7. Cleanup: Next deploy — remove old columns/tables if needed",
]
def show_pipeline(self):
print("=== CI/CD Pipeline ===")
print(self.GITHUB_ACTIONS[:500])
def show_order(self):
print(f"\n=== Deployment Order ===")
for step in self.DEPLOY_ORDER:
print(f" {step}")
pipeline = ZDTPipeline()
pipeline.show_pipeline()
pipeline.show_order()
FAQ - คำถามที่พบบ่อย
Q: EF Migration ต้อง run ก่อน deploy app ใหม่หรือเปล่า?
A: ใช่ — ต้อง migrate database ก่อน deploy app version ใหม่ เพราะ: app ใหม่อาจต้องการ columns/tables ใหม่ที่ migration สร้าง ลำดับ: 1) Apply migration → 2) Deploy new app → 3) Old app ยัง run ได้ (backward compatible) สำคัญ: migration ต้อง backward compatible — old app version ต้อง work กับ schema ใหม่ได้
เนื้อหาเกี่ยวข้อง — อ่านต่อ: Azure Functions Message Queue Design
Q: ถ้า migration ผิดพลาด rollback ยังไง?
แนะนำเพิ่มเติม — XM Signal
A: EF Core: dotnet ef database update [PreviousMigrationName] — rollback ไป migration ก่อนหน้า แต่: ถ้า migration ทำ data transformation — rollback อาจสูญเสียข้อมูล Best practice: backup database ก่อน migrate เสมอ ป้องกัน: test migration บน staging ก่อน production + ใช้ expand-contract pattern
เนื้อหาเกี่ยวข้อง — ดูเพิ่มเติมเรื่อง PostgreSQL JSONB Monitoring และ Alerting — คู่มือฉบับสมบูรณ์ 2026
Q: Expand-Contract ต้องใช้กี่ deploys?
A: ขั้นต่ำ 3 deploys: Deploy 1 (Expand): เพิ่ม column ใหม่ + sync data Deploy 2 (Migrate): app ใช้ column ใหม่เท่านั้น Deploy 3 (Contract): ลบ column เก่า ข้อเสีย: ช้ากว่า deploy เดียว แต่ไม่มี downtime เลย เหมาะกับ: production systems ที่ downtime ยอมรับไม่ได้
แนะนำเพิ่มเติม — เรียนเทรดกับ iCafeForex
เนื้อหาเกี่ยวข้อง — แนะนำให้อ่าน OPA Gatekeeper Database Migration
Q: EF Core กับ Dapper อันไหนดีสำหรับ ZDT?
A: EF Core: มี migration system built-in, schema ผูกกับ model — เปลี่ยน model = ต้อง migrate Dapper: ไม่มี migration (ใช้ FluentMigrator/DbUp แทน), SQL เขียนเอง — flexible กว่า สำหรับ ZDT: ทั้งสองทำได้ — สำคัญคือ migration strategy ไม่ใช่ ORM EF Core ง่ายกว่า: migration tooling ดี, model-first approach Dapper ยืดหยุ่นกว่า: ควบคุม SQL ได้เต็มที่
เนื้อหาเกี่ยวข้อง — แนะนำให้อ่าน จอมอนิเตอร์ 2k — ทุกสิ่งที่ต้องรู้ในปี 2026





