diff --git "a/\345\210\230\346\254\242/20241216--\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" "b/\345\210\230\346\254\242/20241216--\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" new file mode 100644 index 0000000000000000000000000000000000000000..ae625a6a793531a69b54262c7632de696f7dbf7d --- /dev/null +++ "b/\345\210\230\346\254\242/20241216--\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" @@ -0,0 +1,70 @@ +# 连接实际数据库 +## 数据库上下文初始化 +### 使用[有参数]的方案 +1. 在Program.cs文件中添加连接数据库字符串 +```cs +var connectionString = $"Server=.;Database=MdBlog;uid=sa;pwd=123456;TrustServerCertificate=true"; + +builder.Services.AddDbContext(opt => +{ + opt.UseSqlServer(connectionString); +}); +builder.Services.AddScoped(); +``` + +2.在对应的Models文件中,不需要重写OnConfiguring的代码,只需要集成base的代码 +```cs +public BlogDbContext(DbContextOptions options) : base(options) +{ +} +``` + +#### 使用[无参数]的方案!!! +1. 在Program.cs文件中不需要填写任何的代码 +2. 在对应的Models文件中,需要有重写OnConfiguring的代码,继承base的代码则不再需要 +3. 将连接数据库的字符串代码写入重写OnConfiguring的代码中 +```cs +protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) +{ + base.OnConfiguring(optionsBuilder); + + var connectionString = $"Server=.;Database=MdBlog;uid=sa;pwd=123456;TrustServerCertificate=true"; + optionsBuilder.UseSqlServer(connectionString); +} +``` + +### 连接数据库 +1. 在控制器代码中实例化数据库对象 +```cs +private readonly BlogDbContext _db; +public BlogsController() +{ + _db = new BlogDbContext(); +} +``` +2. 将原本的模拟数据库替换成实际数据库 +```cs +Db.Blogs --> _db.Blogs +``` + - 如果改完之后出现`An unhandled exception occurred while processing the request.`的报错,则在主页面表示显示的代码后加上**ToList()** + ```cs + return View(_db.Blogs.ToList()); + ``` +3. 在每次修改(增删改)操作结束之后,都要进行保存,将内容保存到数据库 +```cs +_db.SaveChanges(); +``` +## 打开sql快捷方式 +```cs +win+R services.msc +``` + +## join方法 +是字符串方法,用于将一个数组或集合中的元素连接成一个单一的字符串 + +语法:string.Join("连接符", 字符串数组/集合/对象数组) +```cs +List fruits = new List { "Apple", "Banana", "Cherry" }; +string result = String.Join(", ", fruits); +Console.WriteLine(result); // 输出: Apple, Banana, Cherry +``` \ No newline at end of file diff --git "a/\345\210\230\346\254\242/20241218--\347\224\237\346\210\220\350\277\201\347\247\273\346\226\207\344\273\266.md" "b/\345\210\230\346\254\242/20241218--\347\224\237\346\210\220\350\277\201\347\247\273\346\226\207\344\273\266.md" new file mode 100644 index 0000000000000000000000000000000000000000..0af9ba03a50173f21d30070e669abeef81986cd7 --- /dev/null +++ "b/\345\210\230\346\254\242/20241218--\347\224\237\346\210\220\350\277\201\347\247\273\346\226\207\344\273\266.md" @@ -0,0 +1,39 @@ +### 生成迁移文件 + +#### 命令: +```bash +dotnet ef migrations add FirstInit +``` + +--- + +## 前提条件 + +1. **安装必要的依赖包:** + - **Design 依赖包** + 安装命令: + ```bash + dotnet add package Microsoft.EntityFrameworkCore.Design + ``` + - **全局工具包 (dotnet-ef)** + 安装命令: + ```bash + dotnet tool install --global dotnet-ef + ``` + +2. **程序状态要求:** + - 确保程序没有编译错误,可运行以下命令检查: + ```bash + dotnet build + ``` + - 确保程序未处于运行状态。 + +--- + +#### 同步迁移文件到数据库 + +#### 命令: +```bash +dotnet ef database update +``` + diff --git "a/\345\210\230\346\254\242/20241220--CRUD\346\223\215\344\275\234.md" "b/\345\210\230\346\254\242/20241220--CRUD\346\223\215\344\275\234.md" new file mode 100644 index 0000000000000000000000000000000000000000..dbf7aff622b93409c2286386e99b8dc2680f1ed4 --- /dev/null +++ "b/\345\210\230\346\254\242/20241220--CRUD\346\223\215\344\275\234.md" @@ -0,0 +1,155 @@ +# CRUD 操作实现 + +## 新增 + +### 视图代码 +使用表单提交新增数据: +```cs +@model Baby.Models.Babys; + +
+
+
+
+ +
+``` + +### 控制器代码 +在控制器中实现 `Create` 动作方法: +```cs +public IActionResult Create() +{ + return View(); +} + +[HttpPost] +public IActionResult Create(Babys input) +{ + // 自动生成 Id 并新增数据 + var maxId = Db.Babys.Select(t => t.Id).Max(); + input.Id = maxId + 1; + Db.Babys.Add(input); + + return RedirectToAction("Index"); +} +``` + +--- + +## 编辑 + +### 控制器代码 +实现编辑功能,支持加载数据和保存修改: + +```cs +public IActionResult Edit(int id) +{ + // 获取指定 Id 的记录 + var baby = Db.Babys.FirstOrDefault(x => x.Id == id); + return View(baby); +} + +[HttpPost] +public IActionResult Edit(Babys input) +{ + // 根据 Id 查找记录并更新 + var blog = Db.Babys.FirstOrDefault(x => x.Id == input.Id); + if (blog != null) + { + blog.Title = input.Title; + blog.Content = input.Content; + blog.Author = input.Author; + } + return RedirectToAction("Index"); +} +``` + +--- + +## 删除 + +### 控制器代码 +分两步实现删除操作:显示确认页面和处理删除逻辑。 + +```cs +public ActionResult Delete(int id) +{ + // 查找要删除的记录 + var product = db.Products.Find(id); + if (product == null) + { + return HttpNotFound(); + } + return View(product); +} + +[HttpPost, ActionName("Delete")] +[ValidateAntiForgeryToken] +public ActionResult DeleteConfirmed(int id) +{ + // 确认删除并保存更改 + var product = db.Products.Find(id); + if (product == null) + { + return HttpNotFound(); + } + db.Products.Remove(product); + db.SaveChanges(); + return RedirectToAction("Index"); +} +``` + +--- + +## 查询 + +### 控制器代码 +实现列表展示和单个详情查看: + +```cs +using System.Linq; +using System.Web.Mvc; +using MvcDatabaseConnection.Models; + +public class ProductsController : Controller +{ + private MyDbContext db = new MyDbContext(); + + // 显示产品列表 + public ActionResult Index() + { + var products = db.Products.ToList(); + return View(products); + } + + // 显示单个产品详情 + public ActionResult Details(int id) + { + var product = db.Products.Find(id); + if (product == null) + { + return HttpNotFound(); + } + return View(product); + } +} +``` + +--- + +### 补充说明 + +1. **代码一致性** + - 所有动作方法都严格遵循 `HttpGet` 和 `HttpPost` 的分离原则。 + - 确保模型绑定和验证逻辑正确。 + +2. **防止安全漏洞** + - 对用户输入进行验证,如使用 `[ValidateAntiForgeryToken]` 防范 CSRF 攻击。 + - 确保输入参数的合法性,避免 SQL 注入。 + +3. **UI 优化建议** + - 可使用 `Bootstrap` 样式美化表单和表格,提升用户体验。 + - 在错误提示中使用 `@Html.ValidationSummary()` 或 `@Html.ValidationMessageFor()`。 + +