Technology

C# Entity Framework Low Code No Code

c entity framework low code no code
C# Entity Framework Low Code No Code | SiamCafe Blog
2026-03-04· อ. บอม — SiamCafe.net· 1,674 คำ

C# Entity Framework Low Code No Code คืออะไร

Entity Framework (EF) เป็น Object-Relational Mapper (ORM) ของ .NET ที่ช่วยให้ developers ทำงานกับ database โดยใช้ C# objects แทน SQL โดยตรง Low Code/No Code คือแนวทางพัฒนา applications โดยใช้ visual tools และ configuration แทนการเขียน code จำนวนมาก การรวม Entity Framework กับ Low Code/No Code platforms ช่วยสร้าง data-driven applications ได้เร็วขึ้น 5-10 เท่า เหมาะสำหรับ CRUD applications, admin panels, internal tools และ rapid prototyping

Entity Framework Core Fundamentals

// ef_fundamentals.cs — Entity Framework Core basics
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;

// 1. Define Models
public class Product
{
    public int Id { get; set; }
    
    [Required]
    [MaxLength(200)]
    public string Name { get; set; }
    
    public string Description { get; set; }
    
    [Range(0, 999999)]
    public decimal Price { get; set; }
    
    public int CategoryId { get; set; }
    public Category Category { get; set; }
    
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
    public bool IsActive { get; set; } = true;
}

public class Category
{
    public int Id { get; set; }
    
    [Required]
    public string Name { get; set; }
    
    public ICollection<Product> Products { get; set; }
}

// 2. DbContext
public class AppDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<Category> Categories { get; set; }
    
    public AppDbContext(DbContextOptions<AppDbContext> options) 
        : base(options) { }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>()
            .HasIndex(p => p.Name);
        
        modelBuilder.Entity<Product>()
            .HasOne(p => p.Category)
            .WithMany(c => c.Products)
            .HasForeignKey(p => p.CategoryId);
        
        // Seed data
        modelBuilder.Entity<Category>().HasData(
            new Category { Id = 1, Name = "Electronics" },
            new Category { Id = 2, Name = "Books" }
        );
    }
}

// 3. CRUD Operations
public class ProductService
{
    private readonly AppDbContext _context;
    
    public ProductService(AppDbContext context) => _context = context;
    
    public async Task<List<Product>> GetAllAsync()
        => await _context.Products
            .Include(p => p.Category)
            .Where(p => p.IsActive)
            .OrderBy(p => p.Name)
            .ToListAsync();
    
    public async Task<Product> CreateAsync(Product product)
    {
        _context.Products.Add(product);
        await _context.SaveChangesAsync();
        return product;
    }
    
    public async Task UpdateAsync(Product product)
    {
        _context.Entry(product).State = EntityState.Modified;
        await _context.SaveChangesAsync();
    }
    
    public async Task DeleteAsync(int id)
    {
        var product = await _context.Products.FindAsync(id);
        if (product != null)
        {
            product.IsActive = false; // Soft delete
            await _context.SaveChangesAsync();
        }
    }
}

Code Generation & Scaffolding

# scaffolding.py — EF Core scaffolding commands
import json

class EFScaffolding:
    COMMANDS = {
        "scaffold_from_db": {
            "name": "Database-First Scaffolding",
            "command": "dotnet ef dbcontext scaffold 'Server=.;Database=MyDb;Trusted_Connection=True' Microsoft.EntityFrameworkCore.SqlServer -o Models --context AppDbContext",
            "description": "สร้าง Models + DbContext จาก existing database อัตโนมัติ",
        },
        "add_migration": {
            "name": "Add Migration",
            "command": "dotnet ef migrations add InitialCreate",
            "description": "สร้าง migration จาก model changes",
        },
        "update_database": {
            "name": "Update Database",
            "command": "dotnet ef database update",
            "description": "Apply migrations ไป database",
        },
        "scaffold_controller": {
            "name": "Scaffold API Controller",
            "command": "dotnet aspnet-codegenerator controller -name ProductsController -async -api -m Product -dc AppDbContext -outDir Controllers",
            "description": "สร้าง CRUD API controller อัตโนมัติจาก model",
        },
        "scaffold_pages": {
            "name": "Scaffold Razor Pages",
            "command": "dotnet aspnet-codegenerator razorpage -m Product -dc AppDbContext -udl -outDir Pages/Products --referenceScriptLibraries",
            "description": "สร้าง CRUD pages (Create, Read, Update, Delete) อัตโนมัติ",
        },
    }

    LOW_CODE_APPROACH = """
    EF Core Low-Code Workflow:
    
    1. Define Models (C# classes with annotations)
    2. dotnet ef migrations add → auto-generate DB schema
    3. dotnet ef database update → apply to DB
    4. Scaffold Controllers → auto-generate REST API
    5. Scaffold Razor Pages → auto-generate CRUD UI
    
    Result: Full CRUD app in minutes — ไม่ต้องเขียน SQL, ไม่ต้องเขียน API logic
    """

    def show_commands(self):
        print("=== EF Core Scaffolding ===\n")
        for key, cmd in self.COMMANDS.items():
            print(f"[{cmd['name']}]")
            print(f"  $ {cmd['command'][:80]}...")
            print(f"  {cmd['description']}")
            print()

    def show_workflow(self):
        print("=== Low-Code Workflow ===")
        print(self.LOW_CODE_APPROACH)

scaffold = EFScaffolding()
scaffold.show_commands()
scaffold.show_workflow()

Low Code/No Code Platforms with EF

# lowcode_platforms.py — Low Code platforms for .NET/EF
import json

class LowCodePlatforms:
    PLATFORMS = {
        "blazor_admin": {
            "name": "Blazor Admin Templates",
            "type": "Low Code",
            "description": "Auto-generate admin panel จาก EF models — CRUD, search, pagination built-in",
            "tools": "Radzen Blazor, MudBlazor, Syncfusion Blazor",
            "effort": "Models → Admin UI ใน 1 ชั่วโมง",
        },
        "power_apps": {
            "name": "Microsoft Power Apps",
            "type": "No Code / Low Code",
            "description": "สร้าง apps จาก SQL Server/Azure SQL — connect ผ่าน connector",
            "integration": "EF migrations → SQL Server → Power Apps connector → UI auto-generated",
            "effort": "Drag & drop UI, ไม่ต้องเขียน code",
        },
        "outsystems": {
            "name": "OutSystems",
            "type": "Low Code",
            "description": "Enterprise low-code platform — สร้าง .NET apps visually",
            "integration": "Import DB schema → auto-generate entities → visual logic builder",
            "effort": "Enterprise apps ใน weeks แทน months",
        },
        "tooljet": {
            "name": "ToolJet / Appsmith",
            "type": "Low Code (Open Source)",
            "description": "สร้าง internal tools — connect ตรงกับ database",
            "integration": "Connect SQL Server → drag & drop UI → auto CRUD",
            "effort": "Internal tools ใน hours",
        },
        "abp_framework": {
            "name": "ABP Framework",
            "type": "Low Code (.NET)",
            "description": "Application framework สำหรับ .NET — auto CRUD, auth, multi-tenancy",
            "integration": "Define entity → auto-generate: API, UI, DB migration, tests",
            "effort": "Full module ใน minutes",
        },
    }

    def show_platforms(self):
        print("=== Low Code/No Code Platforms ===\n")
        for key, p in self.PLATFORMS.items():
            print(f"[{p['name']}] ({p['type']})")
            print(f"  {p['description']}")
            print(f"  Effort: {p['effort']}")
            print()

    def comparison(self):
        print("=== Comparison ===")
        print(f"  {'Platform':<20} {'Type':<12} {'Effort':<20} {'Cost'}")
        print(f"  {'-'*65}")
        comparisons = [
            ("EF + Scaffolding", "Low Code", "Hours", "Free"),
            ("Blazor + Radzen", "Low Code", "Hours-Days", "Free/Paid"),
            ("Power Apps", "No Code", "Hours", "$5-40/user/mo"),
            ("ABP Framework", "Low Code", "Minutes-Hours", "Free/Paid"),
            ("ToolJet", "Low Code", "Hours", "Free (OSS)"),
        ]
        for c in comparisons:
            print(f"  {c[0]:<20} {c[1]:<12} {c[2]:<20} {c[3]}")

platforms = LowCodePlatforms()
platforms.show_platforms()
platforms.comparison()

Auto-Generated REST API

// auto_api.cs — Minimal API with EF Core (auto CRUD)
// Program.cs — .NET 8 Minimal API

// var builder = WebApplication.CreateBuilder(args);
// builder.Services.AddDbContext<AppDbContext>(opt =>
//     opt.UseSqlServer(builder.Configuration.GetConnectionString("Default")));
// var app = builder.Build();

// Generic CRUD endpoint generator
public static class CrudEndpoints
{
    public static void MapCrud<T>(
        this WebApplication app, string route) where T : class
    {
        var group = app.MapGroup(route);
        
        // GET all
        group.MapGet("/", async (AppDbContext db) =>
            await db.Set<T>().ToListAsync());
        
        // GET by id
        group.MapGet("/{id:int}", async (int id, AppDbContext db) =>
            await db.Set<T>().FindAsync(id) is T item
                ? Results.Ok(item)
                : Results.NotFound());
        
        // POST create
        group.MapPost("/", async (T item, AppDbContext db) =>
        {
            db.Set<T>().Add(item);
            await db.SaveChangesAsync();
            return Results.Created($"/{route}/{(item as dynamic).Id}", item);
        });
        
        // PUT update
        group.MapPut("/{id:int}", async (int id, T item, AppDbContext db) =>
        {
            db.Entry(item).State = EntityState.Modified;
            await db.SaveChangesAsync();
            return Results.NoContent();
        });
        
        // DELETE
        group.MapDelete("/{id:int}", async (int id, AppDbContext db) =>
        {
            var item = await db.Set<T>().FindAsync(id);
            if (item is null) return Results.NotFound();
            db.Set<T>().Remove(item);
            await db.SaveChangesAsync();
            return Results.NoContent();
        });
    }
}

// Usage — register CRUD for all entities
// app.MapCrud<Product>("/api/products");
// app.MapCrud<Category>("/api/categories");
// app.MapCrud<Order>("/api/orders");
// 3 lines = 15 REST endpoints!

Python Integration Tool

# python_tool.py — Python tool for EF project generation
import json
import os

class EFProjectGenerator:
    CODE = """
# ef_generator.py — Generate EF Core project from schema
import json
import os

class EFCoreGenerator:
    def __init__(self, project_name, entities):
        self.project_name = project_name
        self.entities = entities
    
    def generate_model(self, entity):
        props = []
        for prop in entity['properties']:
            attrs = []
            if prop.get('required'):
                attrs.append('[Required]')
            if prop.get('max_length'):
                attrs.append(f"[MaxLength({prop['max_length']})]")
            
            attr_str = '\\n    '.join(attrs)
            if attr_str:
                attr_str += '\\n    '
            
            props.append(f"    {attr_str}public {prop['type']} {prop['name']} {{ get; set; }}")
        
        return f'''public class {entity['name']}
{{
    public int Id {{ get; set; }}
{chr(10).join(props)}
}}'''
    
    def generate_dbcontext(self):
        dbsets = []
        for entity in self.entities:
            name = entity['name']
            dbsets.append(f"    public DbSet<{name}> {name}s {{ get; set; }}")
        
        return f'''public class AppDbContext : DbContext
{{
{chr(10).join(dbsets)}
    
    public AppDbContext(DbContextOptions options)
        : base(options) {{ }}
}}'''
    
    def generate_all(self, output_dir):
        os.makedirs(f"{output_dir}/Models", exist_ok=True)
        
        for entity in self.entities:
            model = self.generate_model(entity)
            with open(f"{output_dir}/Models/{entity['name']}.cs", 'w') as f:
                f.write(model)
        
        context = self.generate_dbcontext()
        with open(f"{output_dir}/Data/AppDbContext.cs", 'w') as f:
            f.write(context)
        
        return f"Generated {len(self.entities)} models + DbContext"

# Define schema
schema = [
    {"name": "Product", "properties": [
        {"name": "Name", "type": "string", "required": True, "max_length": 200},
        {"name": "Price", "type": "decimal", "required": True},
        {"name": "CategoryId", "type": "int"},
    ]},
    {"name": "Category", "properties": [
        {"name": "Name", "type": "string", "required": True, "max_length": 100},
    ]},
]

generator = EFCoreGenerator("MyApp", schema)
# generator.generate_all("./output")
"""

    def show_code(self):
        print("=== EF Project Generator ===")
        print(self.CODE[:600])

    def demo_output(self):
        print(f"\n=== Generated Project Structure ===")
        files = [
            "MyApp/Models/Product.cs",
            "MyApp/Models/Category.cs",
            "MyApp/Models/Order.cs",
            "MyApp/Data/AppDbContext.cs",
            "MyApp/Controllers/ProductsController.cs",
            "MyApp/Controllers/CategoriesController.cs",
            "MyApp/Pages/Products/Index.cshtml",
            "MyApp/Pages/Products/Create.cshtml",
            "MyApp/Pages/Products/Edit.cshtml",
            "MyApp/Pages/Products/Delete.cshtml",
        ]
        for f in files:
            print(f"  {f}")

gen = EFProjectGenerator()
gen.show_code()
gen.demo_output()

FAQ - คำถามที่พบบ่อย

Q: EF Core กับ Dapper อันไหนดี?

A: EF Core: Full ORM, LINQ queries, migrations, relationships, scaffolding — เหมาะ rapid development Dapper: Micro ORM, เขียน SQL เอง, เร็วกว่า EF 2-5x — เหมาะ performance-critical Low Code: EF Core ดีกว่า — auto-generate ได้มากกว่า High Performance: Dapper ดีกว่า — ควบคุม SQL ได้เต็มที่ ใช้ทั้งคู่ได้: EF Core สำหรับ CRUD ทั่วไป + Dapper สำหรับ complex queries

Q: Low Code เหมาะกับงานอะไร?

A: เหมาะ: Internal tools, Admin panels, CRUD apps, Prototyping, MVP ไม่เหมาะ: Complex business logic, Real-time systems, High-performance, Custom UI มาก กฎ: ถ้า 80% ของ app เป็น CRUD → Low Code คุ้มมาก ถ้า logic ซับซ้อน → เขียน code เอง + ใช้ EF Core scaffolding ช่วย

Q: EF Core performance ดีไหม?

A: ดีขึ้นมากใน EF Core 8: Compiled queries, batch operations, split queries Tips: AsNoTracking() สำหรับ read-only, Include() เฉพาะที่ต้องใช้, Pagination (Skip/Take), Compiled queries สำหรับ hot paths Benchmark: EF Core 8 ใกล้เคียง Dapper สำหรับ simple queries

Q: Database-First หรือ Code-First ดีกว่า?

A: Code-First: เหมาะ new projects — define models → auto-generate DB Database-First: เหมาะ existing DB — scaffold models จาก DB Low Code: Code-First ดีกว่า — ควบคุม schema ได้, migrations ง่าย แนะนำ: Code-First + EF Migrations สำหรับ projects ใหม่ทุกครั้ง

📖 บทความที่เกี่ยวข้อง

Cloudflare Low Code No Codeอ่านบทความ → MongoDB Change Streams Low Code No Codeอ่านบทความ → QuestDB Time Series Low Code No Codeอ่านบทความ → Snyk Code Security Low Code No Codeอ่านบทความ → C# Entity Framework Blue Green Canary Deployอ่านบทความ →

📚 ดูบทความทั้งหมด →