使用 FluentNHibernate 和 Repository 模式在 ASP.NET Web API 中进行 CRUD 操作





5.00/5 (9投票s)
在这篇循序渐进的文章中,我们将讨论使用 Repository 模式在 Web API 中进行所有 CRUD(创建、读取、更新、删除)操作。
引言
在这篇循序渐进的文章中,我们将讨论使用 Repository 模式和最流行的 ORM FluentNHibernate 在 Web API 中进行创建、读取、更新、删除 (CRUD) 操作。本文不会深入探讨如何使用 WEB API。
如果您想将 Web API 作为客户端从第三方使用,我建议阅读以下文章以了解更多信息
为什么选择 WEB API?
在准备这份白皮书时,我问自己一个问题:“为什么选择 Web API?”。简单来说,我们选择 Web API 而不是 WebServices、WCF 或 REST WCF 的原因有很多。
我将它们归类如下
- 特点
- 功能
- 资源
- 行为型
尽管我们不会深入探讨上述内容,因为它超出了我们主要主题的范围,但我仍建议阅读以下内容以更好地理解这些术语
先决条件
要实现并运行源代码,您应该具备
- ASP.NET MVC 的基本知识
- REST 服务的 A基本知识
- FluentNHibernate 的基本知识
- Repository 模式的基本知识
- 需要 Visual Studio 2012 或更高版本并支持 ASP.NET WebAPI
让我们开始创建 ASP.NET Web API 项目
- 启动 Visual Studio 并选择“文件”->“新建项目”(Ctrl + Shift + N)
- 从可用对话框中,选择“Web 模板”->“ASP.NET MVC 4 Web 应用程序”
- 我将其命名为“
CRUDWithWebAPI
”——您可以选择您喜欢的名称添加 ASP.NET web API 应用程序。 - 选择使用 Razor 视图引擎的空 Web API。
添加 ASP.NET web API 应用程序。
文件夹结构
默认情况下,我们会得到这些文件夹
App_Data
App_Start
:包含启动应用程序所需的配置类(例如路由集合等)- Controllers:Web API 的控制器
- Models:包含模型/类
- Scripts:所有脚本和 CSS
- 视图
对上面提到的每个文件夹的更多解释超出了本文的范围。
安装 FluentNHibernate
为您的项目安装 FluentNHibernate 支持
- 使用“视图”->“其他窗口”打开“包管理器控制台”
- 现在输入“
Install-Package FluentNHibernate
”并按 Enter
等待 FluentNHibernate 安装完成。
模型、映射和 Repository 模式
在此步骤中,我们将创建模型及其映射,并添加一个 Repository。
添加模型及其映射
- 要添加模型,右键单击解决方案资源管理器中的Models文件夹并选择类,将其命名为“
ServerData
”。public class ServerData { public virtual int Id { get; set; } public virtual DateTime InitialDate { get; set; } public virtual DateTime EndDate { get; set; } public virtual int OrderNumber { get; set; } public virtual bool IsDirty { get; set; } public virtual string IP { get; set; } public virtual int Type { get; set; } public virtual int RecordIdentifier { get; set; } }
添加模型 - 添加其映射类,右键单击解决方案资源管理器中的Models文件夹并选择类,将其命名为“
ServerDataMap
”。public class ServerDataMap : ClassMap<ServerData> { public ServerDataMap() { Table("ServerData"); Id(x => x.Id, "Id").GeneratedBy.Identity().UnsavedValue(0); Map(x => x.InitialDate); Map(x => x.EndDate); Map(x => x.OrderNumber); Map(x => x.IsDirty); Map(x => x.IP).Length(11); Map(x => x.Type).Length(1); Map(x => x.RecordIdentifier); } }
- 不要忘记添加以下命名空间
using FluentNHibernate.Mapping;
为您的应用程序添加 NHibernate 支持
- 添加新文件夹并将其命名为“Helper”。
- 在“Helper”文件夹下添加一个新类,并将其命名为“
NHibernateHelper
”。 -
在此类中,我们需要配置 NHibernate 并构建所有
sessionfactory
,以便我们的应用程序将与数据库交互private static void CreateSessionFactory() { _sessionFactory = Fluently.Configure() .Database(MsSqlConfiguration.MsSql2008.ConnectionString(connectionString).ShowSql) .Mappings(m => m.FluentMappings.AddFromAssemblyOf<ServerData>()) .ExposeConfiguration(cfg => new SchemaExport(cfg).Create(false, false)) .BuildSessionFactory(); }
我们不会详细讨论所有这些内容,因为它们超出了本文的范围。
- 在“Models”下创建一个新文件夹,并将其命名为“Persistance”。
- 在“Persistance”下添加一个接口“
IServerDataRepository
”。public interface IServerDataRepository { ServerData Get(int id); IEnumerable<ServerData> GetAll(); ServerData Add(ServerData serverData); void Delete(int id); bool Update(ServerData serverData); }
- 在“Persistance”下添加一个类“
ServerDataRepository
”并实现“IServerDataRepository
”。public class ServerDataRepository : IServerDataRepository { //method implementation goes here }
现在,我们的 Repository 已经准备好开始运行了。
有关 Repository 模式的更多详细信息,请参阅 http://msdn.microsoft.com/en-us/library/ff649690.aspx。
添加 Web API 控制器
在此步骤中,我们将创建所有必要的动作方法
- 右键单击文件夹“Controllers”并添加一个新控制器,将其命名为“ServerDataController”(记住选择一个空控制器)
- 它看起来像
public class ServerDataController : ApiController { }
添加以下代码行(它将初始化我们的存储库)。
static readonly IServerDataRepository serverDataRepository = new ServerDataRepository();
添加 web API 空控制器。引用请注意,在本文/演示中,我们不会实现任何 DI 模式或控制反转 (IOC) 框架。
我们现在准备开始游戏。
public IEnumerable<ServerData> GetServerData() { return serverDataRepository.GetAll(); }
请参阅上面定义的方法,为什么我们添加“
Get
”后缀,这是一个很好的做法,可以将“Get
”添加到方法名称中,按照约定它会映射GET
请求。此方法没有任何参数,因此,您可以说它映射的 URI 不包含“
id
”参数。 - 添加以下方法以通过 id 获取
ServerData
。这是一个可选参数,如我们的路由中所定义,ASP.NET Web API 框架会自动将其类型转换为int
。 - 如果
id
无效,它将抛出“HttpResponseException
”异常(在以下方法中,我们将异常转换为 404 NOT Found 异常)。public ServerData GetServerDataById(int id) { var serverData = serverDataRepository.Get(id); if (serverData == null) throw new HttpResponseException(HttpStatusCode.NotFound); return serverData; }
-
以下方法用于按类型获取
ServerData
public IEnumerable<ServerData> GetServerDataByType(int type) { return serverDataRepository.GetAll().Where(d => d.Type == type); }
-
要调用上述方法,我们需要在“WebApiConfig.cs”中定义新路由,如下所示
config.Routes.MapHttpRoute( name: "ProductByType", routeTemplate: "api/{controller}/type/{type}" );
-
类似地
public IEnumerable<ServerData> GetServerDataByIP(string ip) { return serverDataRepository.GetAll().Where(d => d.IP.ToLower() == ip.ToLower()); }
config.Routes.MapHttpRoute( name: "ProductByIP", routeTemplate: "api/{controller}/ip/{ip}" );
-
在这里,我们将使用此方法删除
serverdata
public void DeletServerData(int id) { var serverData = serverDataRepository.Get(id); if (serverData == null) throw new HttpResponseException(HttpStatusCode.NotFound); serverDataRepository.Delete(id); }
-
让我们向控制器添加一个新方法,以添加
ServerData
的新记录。public ServerData PostServerData(ServerData serverData) { return serverDataRepository.Add(serverData); }
上述方法能奏效吗?当然可以,但它不是一个理想的方法,或者说它不够完整,为什么呢?
- 在上面,后缀是“
Post
”,听起来它发送的是 HttpPOST
请求。 - 此外,值得注意的是参数类型为“
ServerData
”。 - 当我们使用 Web API 时,复杂类型参数会从请求正文中反序列化,我们也可以说我们期望客户端提供序列化输入,例如 XML 或 JSON。
- 在上述方法中,我们缺少 HTTP 响应中的以下内容
- 响应代码:默认情况下为 200 (OK),但根据 HTTP 1.1 协议,服务器应回复 201 (created),而
POST
请求会导致资源的创建。 - 位置:每当服务器创建资源时,它应在响应的位置标头中包含新资源的 URI。
- 响应代码:默认情况下为 200 (OK),但根据 HTTP 1.1 协议,服务器应回复 201 (created),而
- 因此,我们可以按以下方法定义的方式实现此功能
public HttpResponseMessage PostServerData(ServerData serverData) { serverData = serverDataRepository.Add(serverData); var response = Request.CreateResponse<ServerData>(HttpStatusCode.Created, serverData); var uri = Url.Link("DefaultApi", new { id = serverData.Id }); response.Headers.Location = new Uri(uri); return response; }
- 最后,我们需要添加一个
update
方法,它很简单public void PutServerData(int id, ServerData serverData) { serverData.Id = id; if (!serverDataRepository.Update(serverData)) throw new HttpResponseException(HttpStatusCode.NotFound); }
从上面我们可以看出,WEB API 将此方法与
PUT
请求匹配,上述方法有两个参数 id 和 serverdata。因此,id 取自 URI 路径,serverdata 从请求正文中反序列化。
引用请注意,默认情况下,Web API 框架从路由中获取简单参数类型,从请求正文中获取复杂类型。
设置默认结果输出类型
我们默认需要 JSON 结果,让我们将以下行添加到 Global.asx.cs 文件或您正在注册路由的文件中
//return JSON response by default
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
测试 Web API 结果
在这里,我使用“Firefox Poster”插件来测试输出。您可以直接从 Firefox 插件目录下载此插件
只需输入 URI 并按下 GET 或您想做的任何操作,您就会得到相应的输出。 :)
接下来做什么?
- 尝试使用更复杂的数据扩展此应用程序
- 在未来的文章中,我们将看到如何使用不同的 REST 客户端(例如 RestSharp、ASP.NET 等)来使用 Web API。
- 您可以从 GitHub 下载完整的代码:https://github.com/garora/somestuff/tree/master/CRUDWithWebAPI
- 您可以在此处找到演示:Demo-webapi
这是一个非常好的视频教程,来自 Questpond,关于“REST(Representational State Transfer)”以了解 REST 服务。
结语
希望您喜欢这篇文章。我尽量使其简单明了。如果您喜欢这篇文章,请给它评分并分享,以分享知识。