MVC3学习第六章 排山倒海第二变----使用 Entity Framework Code-First 进行数据访问
本章学习内容
1.Entity Framework 4.1介绍
2.Entity Framework Code-First 进行数据访问
3.利用EF实现用户的增加和列表功能
1.Entity Framework 4.1介绍
在MX11(微软互联网技术大会)前夕,微软发布了 ADO.NET Entity Framework 4.1 (EF 4.1) 正式版。
EF 4.1有哪些新玩新儿?
1. 首先当然是DbContext API,它是基于以前版本中的ObjectContext和其他一些类型抽象出的一个简单的API,针对常用开发场景和编程模式进行了优化。DbContext可以被于Database First, Model First, Code First三种开发模式。
2. Code First是基于Entity Framework的新的开发模式,原先只有Database First和Model First两种。Code First顾名思义,就是先用C#/VB.NET的类定义好你的领域模型,然后用这些类映射到现有的数据库或者产生新的数据库结构。Code First同样支持通过Data Annotations或fluent API进行定制化配置。
如何拥有EF 4.1?
1. 去微软官方网站下载:ADO.NET Entity Framework 4.1。
2. 在VS2010中通过NuGet将 ‘EntityFramework’ NuGet package 添加到你的项目中,但这个只包含Entity Framework运行时,不包含VS2010文件模板(用于Model First与Database First开发模式)。
如何使用EF 4.1?
可以去下面几个地方逛逛:
1. ADO.NET Entity Framework page on the MSDN Data Developer Center
2. MSDN Documentation
3. ADO.NET Entity Framework Forum
4. Code First walkthrough
5. Model First / Database First walkthrough
友情提醒:别忘了去博客园Entity Framework专区。
详情参考http://news.cnblogs.com/n/97213/
很可能你没有用过任何版本的Entity Framework,上面的描述你不太明白,你也不知道那些新特性在以前的版本中是什么样子,没有关系,在我们后续的使用中你会了解他,也会熟练的使用它,享受它的种种特性给你带来的编码便利。
另外说明一下,一开始我就说了我用的是vs2010 sp1,所以我没有额外下载Entity Framework4.1安装包,新建MVC3项目时也没有额外添加该引用,vs已帮我自动完成这些,如果是使用的vs2010还要额外下载安装包并添加引用。
2.利用Entity Framework Code-First 进行数据访问
我们将使用包含在 ASP.NET MVC3 中的 Entity Framework (EF) 支持进行查询和更新数据库中的数据。EF 是一个灵活的进行数据访问的对象关系映射 API,允许开发人员使用面向对象的方式对数据库中的数据进行查询和更新。
Entity Framework 4 支持一种称为代码优先的开发模式,代码有限允许你通过编写简单的类来创建模型对象(也被称为 POCO, 简单的,老的 CLR 对象),然后通过类来创建数据,这与我们传统的应用程序先创建数据库再来编写实体以及后续逻辑处理或许有点稍微不同,不过无所谓,大道同归,让我们先不打开熟悉的SQLSERVER2005数据库,先把vs里的事情做好。
如同以往连接数据库一样,打开web.cofig文件,添加连接字符串,完整web.config代码如下:
<?xml version="1.0" encoding="utf-8"?> <!--有关如何配置 ASP.NET 应用程序的详细信息,请访问http://go.microsoft.com/fwlink/?LinkId=152368--><configuration><connectionStrings><add name="MyShopDataEntities" connectionString="Data Source=.;Initial Catalog=MyShop;User ID=sa;Password=sa;Integrated Security=true;" providerName="System.Data.SqlClient"></add></connectionStrings><appSettings><add key="webpages:Version" value="1.0.0.0"/><add key="ClientValidationEnabled" value="true"/><add key="UnobtrusiveJavaScriptEnabled" value="true"/><!--此处是上传文件相关配置--><add key="upFileType" value=".doc|.docx|.rar|.zip|.xls|.xlsx|.ppt|.pptx|.txt|.jpg|.gif|.pdf|.html|.htm|.mht" /><add key="upImageType" value=".jpg|.gif|.ico|.bmp|.png" /><add key="upVideoType" value=".avi|.wmv|.mpeg|.rmvb" /><add key="upFileSize" value="10" /><add key="upFilePath" value="/UpFile" /><add key="isWater" value="false" /><add key="WaterType" value="1" /><add key="WaterText" value="MVC测试" /><add key="TextSize" value="12" /><add key="WaterImg" value="none" /></appSettings><system.web><compilation debug="true" targetFramework="4.0"><assemblies><add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /><add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /><add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /><add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /><add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /></assemblies></compilation><authentication mode="Forms"><forms loginUrl="~/Account/LogOn" timeout="2880" /></authentication><membership><providers><clear/><add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices"enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"applicationName="/" /></providers></membership><profile><providers><clear/><add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" /></providers></profile><roleManager enabled="false"><providers><clear/><add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" /><add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" /></providers></roleManager><pages><namespaces><add namespace="System.Web.Helpers" /><add namespace="System.Web.Mvc" /><add namespace="System.Web.Mvc.Ajax" /><add namespace="System.Web.Mvc.Html" /><add namespace="System.Web.Routing" /><add namespace="System.Web.WebPages"/></namespaces></pages></system.web><system.webServer><validation validateIntegratedModeConfiguration="false"/><modules runAllManagedModulesForAllRequests="true"/></system.webServer><runtime><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /><bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" /></dependentAssembly></assemblyBinding></runtime> </configuration>
我们在web.config中加入了连接字符串和一些上传文件的配置节点(当然这些与目前的数据库访问没有关系,后续会用到,所以我们一次加了进来),我们加入的数据库连接字符串为“Data Source=.;Initial Catalog=MyShop;User ID=sa;Password=sa;Integrated Security=true;”,这是我的电脑上连接sqlserever2005的字符串,大家请根据自己机器情况加入适宜的连接字符串。
注意:这里的连接字符串的名称很重要,这与我们紧接着要添加的操作数据库色上下文类名称要保持一致,这样这个类才能找到对应的连接字符串来操作数据库。
右键Models,添加数据库操作类,命名为MyShopDataEntities,如图
修改该类完整代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data.Entity;namespace MyShopTest.Models {/// <summary>/// 数据访问,类名称必须和数据库连接字符串的name一致,没有数据库的话,系统会根据连接字符串以及下面的数据映射关系,创建对应的类的数据表/// </summary>public class MyShopDataEntities : DbContext{//实体和数据表的映射public DbSet<UserInfo> UserInfos { get; set; }} }
对于 Code First 来说,我们首先定义模型,然后通过模型来创建数据库,甚至也不需要写 Insert 语句,我们可以通过标准的 C# 代码来创建表中的记录。
注意,这里使用了 System.Data.Entity 命名空间。记得要 using 一下。不需要其他的配置,特定的接口等等,通过扩展 DbContext 基类我们就能直接操作数据库进行增删改查了。
3.利用EF实现用户的增加和列表功能
用户的摸型实体和数据库操作都有了,我们还缺少控制器和对应的视图,前文说到过在MVC3里,页面展示顺序是从控制器到视图的,那么我们创建这二者的顺序也这样开始,便于理解。
右键Controllers文件夹,添加>控制器,模版选择为空控制器,当然选择其他两项包含读写操作的控制器也可以,甚至更为强大和便捷,不过那是我们以后要选择的,万丈高楼平地起,等我们打好了地基再一个一个收拾,命名为UserInfoController,记住所有的控制器命名都以Controller结尾,点击添加完成
UserInfo控制器创建完成了,我们之前已经列举过控制器的代码了,此次就不再解说了,开头说了我们本章要实现的目标是实现用户增加和列表页面,那么我们先从列表页开始
修改UserInfoController代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using MyShopTest.Models; namespace MyShopTest.Controllers {public class UserInfoController : Controller{//数据访问private MyShopDataEntities db = new MyShopDataEntities();/// <summary>/// 用户列表Action/// </summary>/// <returns></returns>public ActionResult Index(){var users = db.UserInfos.ToList();return View(users);}} }
列表的Action有了,他利用EF获取了全部的用户,返回了一个List泛型集合,返回到哪里呢,返回给了View,返回给了ActionResult,最终是将一个List集合返回到了它对应的视图。现在我们来添加对应的视图展示这些数据,右击Index()方法任意处,添加视图
把使用布局或母版页下方选择框里的内容清空,我们直接使用默认的母版页,其他部分包括名称全部默认,后续我们会一一探索这些选项的作用,目前先不管。
视图创建成功,此处直接修改视图代码如下:
@model IEnumerable<MyShopTest.Models.UserInfo> @{ViewBag.Title = "用户列表"; } <h2>用户列表</h2> <p><a href="/UserInfo/Create">添加用户</a> </p> <table><tr><th>用户名</th><th>电话</th><th>邮箱</th><th>注册时间</th><th>操作</th></tr>@foreach (var item in Model){<tr><td>@item.UserName</td><td>@item.Phone</td><td>@item.Email</td><td>@item.AddTime</td><td>暂无操作</td></tr>} </table>
Razor视图我们之前已经用来整整一章的内容来讲述它,在此就不一一回顾了,不过毕竟是我们自己亲手添加的第一个完整视图,我们将其中的代码做一分析。
先看
@model IEnumerable<MyShopTest.Models.UserInfo>
头部的这段代码,model是在Razor视图的关键字,通过他允许我们在视图模版中直接访问在控制器类中通过使用强类型的模型“Model”传递过来的数据,换句话说,这个model关键字代表的其实是页面显示的数据来源,它的类型由Action传过来的数据而决定,此处我们用的是IEnumerable,也可以用List,不过IEnumerable是公开枚举器,该枚举器支持在指定类型的集合上进行简单迭代 List ArrayList 等 就实现的该接口,比List更加宽泛一些。
再看
@{ViewBag.Title = "用户列表"; }
这就不用解释了,表示该页面的标题,如果不设置,默认是母版页的
三看
@foreach (var item in Model){<tr><td>@item.UserName</td><td>@item.Phone</td><td>@item.Email</td><td>@item.AddTime</td><td>暂无操作</td></tr>}
此处代码也不难理解,循环Action传过来的集合,输出值,有一点说明一下,无论是在此处还是在前面的Action里我们都使用了var来作为参数类型,或许有的人会说了,这会导致系统效率的问题,其实不然,可能你会认为使用 var 定义变量使用了迟绑定,这是不正确的,C# 编译器使用赋予变量的值来推定变量的类型,所以并不会导致效率问题,不信我们直接使用var定义的变量看一下,vs的智能提示会直接给出对应类型的提示信息,大家可以试试。
接下来我们来实现我们的添加操作,之后再对代码一一解析,首先修改UserInfoController控制器,添加处理用户添加的Action。修改完整代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using MyShopTest.Models; namespace MyShopTest.Controllers {public class UserInfoController : Controller{//数据访问private MyShopDataEntities db = new MyShopDataEntities();/// <summary>/// 用户列表Action/// </summary>/// <returns></returns>public ActionResult Index(){var users = db.UserInfos.ToList();return View(users);}/// <summary>/// 添加用户页面展示/// </summary>/// <returns></returns>public ActionResult Create(){return View();}/// <summary>/// 添加用户处理/// </summary>/// <returns></returns> [HttpPost]public ActionResult Create(UserInfo user){db.UserInfos.Add(user);db.SaveChanges();return RedirectToAction("Index");}} }
我们给代码添加了两个Action,名称均为Create,我们解释一下这两个Action
第一个
/// <summary>/// 添加用户页面展示/// </summary>/// <returns></returns>public ActionResult Create(){return View();}
注释写到,这是展示添加用户页面的Action,他没有任何逻辑处理操作,只是让他返回到对应的视图,我们之前说过,Asp.net MVC里页面处理流程是先访问Action,再回到视图,所以这个Action的作用就是展示添加页面之用。
第二个
/// <summary>/// 添加用户处理/// </summary>/// <returns></returns> [HttpPost]public ActionResult Create(UserInfo user){db.UserInfos.Add(user);db.SaveChanges();return RedirectToAction("Index");}
代码也相当简练,定义了一个UserInfo类型的参数,db.UserInfos.Add(user)的意思是将user实体添加到EF,user从何而来呢,就是这个方法的参数user,或许这里有些看不明白,传统的webform里我们都需要new一个实体类型,然后依次为里面的字段赋值,每次都市重复这样的过程,MVC里微软帮我们做了这些事,我们定义好实体类型参数,系统会自动一一匹配前台的表单数据,匹配点就是你前台的表单名称要和该实体的属性名一致,这样我们就不需要在使用Request.Form[Key]来取值了。 db.SaveChanges();保存数据更改,这一句代码是必须的,有了这一句应用程序才会将数据写入数据库。return RedirectToAction("Index")的意思是跳转到某个Acton,在这里我们跳到本控制器的Index Action.至于方法头部的HttpPost,表示该方法接受HttpPost请求,他还有HttpGet等其他形式,如果没有写,代表二者都可以处理。
添加Creat视图,右键任意一个Create任意处,添加视图,完整代码如下
@model MyShopTest.Models.UserInfo @{ViewBag.Title = "添加用户"; } <h2>添加用户</h2> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @using (Html.BeginForm()) {<fieldset><legend>添加用户</legend><div class="editor-label">用户名</div><div class="editor-field"><input type="text" name="UserName" /></div><div class="editor-label">密码</div><div class="editor-field"><input type="password" name="UserPwd" /></div><div class="editor-label">电话</div><div class="editor-field"><input type="text" name="Phone" /></div><div class="editor-label">邮箱</div><div class="editor-field"><input type="text" name="Email" /><input type="hidden" name="AddTime" value="@DateTime.Now"/></div><p><input type="submit" value="添加" /></p></fieldset> } <div><a href="Index">返回列表</a> </div>
现在我们来逐一看一下这段代码
@model MyShopTest.Models.UserInfo @{ViewBag.Title = "添加用户"; }
设置model是UserInfo,设置标题
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
这里面的@Url.Content是虚拟路径转换为程序绝对路径,比如说,程序位于 http://www.abc.com/bbs 下,那么你期待的是 http://www.abc.com/bbs/Content/Site.min.css 不转化,就会成了http://www.abc.com/Content/Site.min.css,这里的Content与程序里的Content文件夹密切相关。
@using (Html.BeginForm()) { 省略期间代码 }
@using (Html.BeginForm())表示使用HtmlHelper 开始一个表单,@Html是一个用于视图中生成 Html 的实用工具,使用它可以保持我们的视图清楚和易读 ,Html.BeginForm()表示开始一个表单,默认提交方式为post,默认提交到当前视图对应的Action,它有很多重载的函数,可以帮助我们手动指定Form提交的参数,比如Html.BeginForm("Create", "StoreManager", FormMethod.Post, new { enctype = "multipart/form-data" }),这表示的就是将飙到提交到StoreManager控制器的Create的Action,并且指定提交方式是Post,使用流的形式提交表单。
到此处,有关用户添加和列表的操作我们已经完成了,我们来测试一下效果,为了我们避免我们自己输入地址栏,请打开_Layout.cshtml共享页面,添加用户管理的链接,完整代码如下
<!DOCTYPE html> <html> <head><title>@ViewBag.Title</title><link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" /><script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> </head> <body><div class="page"><div id="header"><div id="title"><h1>我的商店</h1></div><div id="logindisplay">此处是预留注册登陆处</div><div id="menucontainer"><ul id="menu"><li>@Html.ActionLink("主页", "Index", "Home")</li><li>@Html.ActionLink("关于", "About", "Home")</li><li>@Html.ActionLink("用户管理", "Index", "UserInfo")</li></ul></div></div><div id="main">@RenderBody()</div><div id="footer"></div></div> </body> </html>
运行项目,点击用户管理
点击添加用户,输入信息,点击添加
系统自动返回列表页,数据已经出现。
到此为止我们已经实现了数据库的增加和查询操作,但是到目前为止我们甚至连数据都没有打开过,这在以前的传统Webform里几乎是不可能的,事实是我们做到了,我们不得不佩服Entity Framework的强大,也不得不佩服微软的技术实力及其前瞻性。建议大家回顾一下代码,从Model到Controller到Action到View,假如你用过java,了解java的SSH框架,或许理解会更快一些,SSH中的数据库操作是通过Hibernate来操作的,不过可能会需要配置一些复杂的xml映射关系,在保存数据时比Asp.net更早的实现了获取一个Fom直接来保存,当然前提是jsp里必须要一一对应表单数据,这些操作换到asp.net MVC上,所有这些操作微软几乎都帮我们完成了。
末了,我们再看一下,我们之前的代码帮我们创建了什么样的数据库,打开Sqlserver2005,打开连接字符串的数据库
我们可以看到,系统自动帮我们创建了MyShop数据库,建立好了UsrtInfo表,所有的字段都和UserInfo Entity对应好了,主键也已设置,是不是很神奇?我们来解释一下这个过程,EF通过连接字符串来访问数据库,如果没有检测到数据库系统会根据连接字符串创建对应的数据库,然后再检测数据库上下文类里的实体信息,创建对应的映射表。过程就是这样,或许大家还有疑问,EF是怎样区分主外键的?外键的问题我们后续创建商品相关操作时会涉及到,暂时先来看看主键,根据约定,系统会查找实体模型类里是否存在Id或者类名+Id的属性,如果存在,将会以此为主键,如果不存在,则会报错,有兴趣的可以试试。当然我们也可以自由指定主键,这个也在后续了解。
转载于:https://www.cnblogs.com/hswh/p/3150743.html
MVC3学习第六章 排山倒海第二变----使用 Entity Framework Code-First 进行数据访问相关推荐
- Java基础学习——第六章 面向对象编程(下)
Java基础学习--第六章 面向对象编程(下) 一.关键词:static 1. static关键字的引入 当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new ...
- STM32固件库(标准外设库)入门学习 第六章TIM定时器(一)
STM32固件库(标准外设库)入门学习 第六章TIM定时器(一) 文章目录 STM32固件库(标准外设库)入门学习 第六章TIM定时器(一) 前言 一.定时器类型 1 基本定时器 2 通用定时器 3 ...
- [翻译] 神经网络与深度学习 第六章 深度学习 - Chapter 6 Deep learning
目录: 首页 译序 关于本书 关于习题和难题 第一章 利用神经网络识别手写数字 第二章 反向传播算法是如何工作的 第三章 提升神经网络学习的效果 第四章 可视化地证明神经网络可以计算任何函数 第五章 ...
- 《谁说菜鸟不会数据分析》学习笔记 第一章总览 第二章数据分析思路
网上的信息太琐碎了,根本没搞懂什么是数据分析方法什么是数据分析方法论,所以找了一本比较简单的书来系统学习一下,本来打算粗略看完,但是觉得这本书知识还是不错的,所以决定在未来一周把这本书用心学一下. 这 ...
- datawhale可视化学习第六章 场景案例显神通
数据可视化的图表种类繁多,各式各样,因此我们需要掌握如何在特定场景下使用特定的图表. 数据可视化是为业务目的服务的,好的可视化图表可以起到清晰准确反映业务结果的目的,在选择使用何种图表时,通常我们需要 ...
- 计算机组成原理学习-第六章 中央处理器(详细、系统)
如果你对其他计算机组成原理知识感兴趣,请考虑阅读我的专栏: 计算机组成原理[专栏] 须知 本文仅作学习笔记使用,仅在CSDN网站发布,如果在其他网站发现,均为侵权行为,请举报.作者:小王在努力. 参考 ...
- MVC3学习第十三章 佟掌柜第二弹——MVC3下利用陕北吴旗娃的分页控件实现数据分页...
本章学习内容 1.了解陕北吴旗娃的Mvc分页控件 2.利用分页控件实现MVC3下的商品分页 3.利用分页控件实现MVC3下一个页面多个分页以及ajax分页效果 1.了解陕北吴旗娃的Mvc分页控件 在w ...
- Kotlin学习笔记 第一章开始 第二章 基础
参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 本系列为参考Kotlin中文文档 https://download.csdn.net/dow ...
- Intel汇编语言程序设计学习-第六章 条件处理-上
条件处理 本章要点 1.简介 2.布尔和比较指令 3.条件跳转 4.条件循环指令 5.条件结构 6.应用:有限状态机 7.决策伪指令 6.1 简介 本章,读者将看到高级条件分支如何翻译成底层的实现代 ...
最新文章
- 2015.7.16(小高开忍住没有减仓,大盘涨3.5%,百股涨停——买进中重、中航,指导WXL错误)...
- Smali源代码分析教程(转)
- java mapper control_java spring boot中怎么编写mapper?怎么编写service和controller?
- python控制结构实训_Python 控制结构
- java面向对象封装之有参无返与有参有返
- 【HDU - 6514】Monitor(二维差分,前缀和)
- Java 200+ 面试题补充 ThreadLocal 模块
- 认识Linux系统服务(鸟哥18章)
- 【报告分享】阿里妈妈:熬夜真相-0点经济报告.pdf(附下载链接)
- hget如何获取多个value_《深入微服务》之 如何给老婆解释什么是微服务的基础框架SpringBoot?...
- [转载] Pytorch基础介绍
- pycharm添加python注释头_Pycharm自动添加头注释
- cas 怎么过滤带pathvariable_屋顶花池怎么做
- 条形码类型及其字符集和长度的说明
- eset smart security 无法更新的解决方案
- 【软技能】完全写作指南--PPT演讲
- Java基础笔记day01
- Hadoop部署(一) Ubantu Java JDK安装
- 黑科技时代,不了解这些你就OUT了
- 计算机系统结构复习(五):ILP指令集并行
热门文章
- 软件_mongo占用磁盘空间过大
- 各种机器学习的应用场景分别是什么
- 运算除法的计算机函数,2、Python基础--除法、常用数学函数(示例代码)
- linux基本管理命令,linux常用命令与基本管理
- 部队计算机考试题,2020军队文职计算机知识:计算机考试练习题(1)
- 大学计算机基础实训指导第四版,大学计算机基础:学习指导与实训篇(第4版)...
- vue路由配置src/router/index.js
- python狗屁不通文章生成器_狗屁不通文章生成器,GitHub火爆的万字啰嗦文章瞬间生成...
- linux tensorflow demo_独家 | 在浏览器中使用TensorFlow.js和Python构建机器学习模型(附代码)...
- 数据结构 2-3-1 线性表的单链表实现