1. 项目概述:基于.NET Core的外卖订餐系统开发指南
这个外卖订餐系统项目是我去年带团队开发的一个实战案例,特别适合.NET Core初学者从理论过渡到实际项目开发。系统采用前后端分离架构,后端使用.NET Core Web API构建,前端采用Vue.js+Element UI组合,数据库访问层使用EF Core Code First模式。整个项目代码量约1.2万行,完整实现了从菜品管理、订单处理到用户评价的全业务流程。
提示:选择外卖系统作为学习项目有三大优势 - 业务场景熟悉、功能模块完整、技术栈覆盖面广。我在教学实践中发现,这类贴近生活的项目能让开发者更快理解技术实现逻辑。
2. 技术栈选型与架构设计
2.1 后端技术决策
选择.NET Core 3.1作为后端框架主要基于以下考量:
- 跨平台支持:可在Windows/Linux/macOS部署
- 高性能:基准测试显示其吞吐量比.NET Framework高30%
- 内置依赖注入:简化组件管理
- 与EF Core深度集成
数据库选用SQL Server 2019,主要因为:
- 与.NET生态完美兼容
- 提供本地开发免费版(Developer Edition)
- EF Core对其支持最完善
2.2 前端技术组合
Vue 2.x + Element UI的选择理由:
- 渐进式框架学习曲线平缓
- 组件化开发模式与后端API天然契合
- Element UI提供现成的餐饮行业UI组件(如菜品卡片、购物车等)
3. 后端核心实现详解
3.1 项目初始化与配置
创建WebAPI项目建议使用以下命令:
bash复制dotnet new webapi -n FoodDelivery.API --no-https
--no-https参数在开发阶段可简化证书配置,生产环境应移除。
关键NuGet包引用:
xml复制<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.18" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.18"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.18"/>
3.2 领域模型设计
典型的外卖系统核心模型包括:
csharp复制public class Restaurant
{
public int Id { get; set; }
[Required, MaxLength(100)]
public string Name { get; set; }
// 其他属性...
}
public class MenuItem
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Column(TypeName = "decimal(18,2)")]
public decimal Price { get; set; }
// 关联关系...
}
注意:价格字段必须使用decimal类型而非float,避免浮点运算精度问题。Column特性明确指定SQL数据类型。
3.3 数据库上下文配置
DbContext的典型配置:
csharp复制public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<Restaurant> Restaurants { get; set; }
public DbSet<MenuItem> MenuItems { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MenuItem>()
.HasIndex(m => m.Name)
.IsUnique();
}
}
在Startup.cs中注册服务:
csharp复制services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("Default")));
4. 前端开发关键实现
4.1 Vue项目初始化
推荐使用Vue CLI创建项目:
bash复制vue create food-delivery-frontend
关键依赖安装:
bash复制npm install element-ui axios vuex vue-router
4.2 核心组件开发
菜品列表组件示例:
vue复制<template>
<el-row :gutter="20">
<el-col :span="6" v-for="item in menuItems" :key="item.id">
<el-card :body-style="{ padding: '0px' }">
<img :src="item.imageUrl" class="food-image">
<div style="padding: 14px;">
<span>{{ item.name }}</span>
<div class="bottom">
<span class="price">¥{{ item.price }}</span>
<el-button type="text" @click="addToCart(item)">加入购物车</el-button>
</div>
</div>
</el-card>
</el-col>
</el-row>
</template>
<script>
export default {
data() {
return {
menuItems: []
}
},
async created() {
const { data } = await this.$http.get('/api/menu');
this.menuItems = data;
}
}
</script>
5. 系统集成与部署
5.1 API接口设计规范
采用RESTful风格设计:
- GET /api/restaurants - 获取餐厅列表
- POST /api/orders - 提交新订单
- GET /api/orders/{id} - 获取订单详情
使用DTO隔离领域模型:
csharp复制public class OrderDto
{
public int Id { get; set; }
public DateTime OrderTime { get; set; }
public decimal TotalAmount { get; set; }
}
5.2 跨域解决方案
在Startup.cs中配置CORS:
csharp复制services.AddCors(options =>
{
options.AddPolicy("AllowVueClient",
builder => builder.WithOrigins("http://localhost:8080")
.AllowAnyMethod()
.AllowAnyHeader());
});
6. 开发经验与避坑指南
6.1 EF Core性能优化
- 禁用跟踪查询:
csharp复制var restaurants = await _context.Restaurants
.AsNoTracking()
.ToListAsync();
- 批量插入优化:
csharp复制// 错误方式 - 每次Add都会生成SQL
foreach(var item in items) {
context.Add(item);
await context.SaveChangesAsync();
}
// 正确方式 - 单次批量提交
context.AddRange(items);
await context.SaveChangesAsync();
6.2 Vue状态管理实践
对于购物车等全局状态,建议使用Vuex:
javascript复制// store.js
export default new Vuex.Store({
state: {
cartItems: []
},
mutations: {
ADD_TO_CART(state, item) {
const existing = state.cartItems.find(i => i.id === item.id);
existing ? existing.quantity++ : state.cartItems.push({...item, quantity: 1});
}
}
})
7. 项目扩展方向
完成基础功能后,可以考虑:
- 实时订单通知 - 集成SignalR
- 支付对接 - 支付宝/微信支付SDK
- 微服务改造 - 拆分为订单服务、菜单服务等
- Docker容器化部署
我在实际开发中发现,合理的日志记录对排查线上问题至关重要。建议使用Serilog记录结构化日志:
csharp复制Log.Information("订单 {@Order} 创建成功", order);