使用 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 应用程序。 添加 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; }
- 	以下方法用于按类型获取 ServerDatapublic 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}" );
- 	在这里,我们将使用此方法删除 serverdatapublic 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 服务。
结语
希望您喜欢这篇文章。我尽量使其简单明了。如果您喜欢这篇文章,请给它评分并分享,以分享知识。









