提交 31e34f17 编写于 作者: W wizardforcel

2022-01-08 19:04:01

上级 f2467a6f
......@@ -792,7 +792,7 @@ public Guid ProjectId { get; set; }
在面向对象的语言中,我们有类继承,这是关系数据库所没有的。我们如何将它存储在关系数据库中?
马丁·福勒在他的开创性著作《企业应用程序架构的模式》中描述了在关系数据库中保持类层次结构的三种模式:
马丁·福勒在他的开创性著作《企业应用架构的模式》中描述了在关系数据库中保持类层次结构的三种模式:
1. 单表继承或每个类层次结构的表:单个表用于表示整个层次结构;它包含所有类的所有映射属性的列。其中许多将为空,因为它们将只存在于一个特定的类中;一个区别列将存储一个值,该值将告诉实体框架特定记录将映射到哪个类。
......
......@@ -182,7 +182,7 @@ ctx.Entry(project).Reload();
### 概述
乐观并发控制是一种使用数据库的方法,它假设多个事务可以在不相互影响的情况下完成;不需要锁定。提交记录时,每个事务都将检查数据库中的记录是否已被修改,并将失败。这对于在 web 应用程序的上下文中处理对数据的多次访问非常有用。
乐观并发控制是一种使用数据库的方法,它假设多个事务可以在不相互影响的情况下完成;不需要锁定。提交记录时,每个事务都将检查数据库中的记录是否已被修改,并将失败。这对于在 web 应用的上下文中处理对数据的多次访问非常有用。
有两种方法可以处理数据被更改的情况:
......@@ -297,7 +297,7 @@ modelBuilder.Entity<Project>().Property(x => x.RowVersion).IsRowVersion();
## 分离的实体
web 应用程序中的一个常见场景是这样的:从数据库中加载某个实体,将其存储在会话中,然后在后续请求中,从那里获取它并继续使用它。这一切都很好,除了,如果您使用的是实体框架代码优先,您将不会在两个请求上使用相同的上下文实例。这个新的上下文对这个实例一无所知。在这种情况下,据说实体相对于上下文是分离的。这样做的效果是,不会跟踪对此实例的任何更改,也不会加载在会话中存储时未加载的任何延迟加载属性。
web 应用中的一个常见场景是这样的:从数据库中加载某个实体,将其存储在会话中,然后在后续请求中,从那里获取它并继续使用它。这一切都很好,除了,如果您使用的是实体框架代码优先,您将不会在两个请求上使用相同的上下文实例。这个新的上下文对这个实例一无所知。在这种情况下,据说实体相对于上下文是分离的。这样做的效果是,不会跟踪对此实例的任何更改,也不会加载在会话中存储时未加载的任何延迟加载属性。
我们需要做的是将这个实例与新的上下文相关联。
......
......@@ -2,7 +2,7 @@
## 概述
我们生活在一个互联的世界里,如今分布式应用程序很常见。微软。NET 堆栈提供了一些有趣的技术,通过利用实体框架向外部世界公开实体。在接下来的几页中,我们将讨论两种 web 服务技术和一种动态 CRUD 接口技术。
我们生活在一个互联的世界里,如今分布式应用很常见。微软。NET 堆栈提供了一些有趣的技术,通过利用实体框架向外部世界公开实体。在接下来的几页中,我们将讨论两种 web 服务技术和一种动态 CRUD 接口技术。
[WCF 数据服务](http://msdn.microsoft.com/en-us/library/cc668792.aspx)是微软实施的 [OData](http://www.odata.org) 标准。基本上,这是发布、查询和交换来自实体的数据的标准,例如 REST web 服务,它是在 WCF 之上实现的。您可以通过 URL 发出查询,甚至可以生成使用 LINQ 查询发布模型的强类型代理。
......
......@@ -77,7 +77,7 @@ var allProjectsSQL = ctx.Projects.ToSqlString();
## 微型先验仪
[MiniProfiler](http://miniprofiler.com/) 是一个开源项目,为 ASP.NET MVC 和实体框架提供了一个代码分析器。我将演示如何在 MVC 项目中使用它,但是除了 MVC 控制台之外,它还可以用在 Windows 窗体、控制台甚至 Web 窗体应用程序中。
[MiniProfiler](http://miniprofiler.com/) 是一个开源项目,为 ASP.NET MVC 和实体框架提供了一个代码分析器。我将演示如何在 MVC 项目中使用它,但是除了 MVC 控制台之外,它还可以用在 Windows 窗体、控制台甚至 Web 窗体应用中。
要使用它,需要先从 [NuGet](http://www.nuget.org/packages/MiniProfiler/) 获取它的核心包。
......@@ -161,7 +161,7 @@ var parameters = timings.First().Parameters;
图 57: SQL Server 事件探查器输出
您注意到“应用程序名称”栏了吗?实体框架总是将应用程序名称设置为“EntityFrameworkMUE”,这样您总是可以知道它发送了哪些 SQL 查询,并且您可以在 SQL Server Profiler 上创建一个过滤器来仅显示这些条目。如果需要,可以通过在连接字符串中提供应用程序名称参数来指定不同的应用程序名称。
您注意到“应用名称”栏了吗?实体框架总是将应用名称设置为“EntityFrameworkMUE”,这样您总是可以知道它发送了哪些 SQL 查询,并且您可以在 SQL Server Profiler 上创建一个过滤器来仅显示这些条目。如果需要,可以通过在连接字符串中提供应用名称参数来指定不同的应用名称。
```cs
<connectionStrings>
......
......@@ -7,7 +7,7 @@
* EFCF 假设了 dbo 的数据库模式,这在其他数据库中是不存在的,所以我们被迫在每个实体的映射中指定一个模式。
* 一些。其他一些数据库不支持. NET 类型,例如枚举类型、Guid、[数据库几何](http://msdn.microsoft.com/en-us/library/system.data.spatial.dbgeometry.aspx)[数据库地理](http://msdn.microsoft.com/en-us/library/system.data.spatial.dbgeography.aspx)
* 数据库数据类型,即使概念上相同,也有不同的名称。例如,SQL Server 中的可变长度 Unicode 字符串称为 NVARCHAR,而在 Oracle 中则称为 VARCHAR2。需要指定时要小心。
* 一些等价类型略有不同。例如,在 SQL Server 中,dateTIME 属性可以转换为同时具有日期和时间部分的 DateTime 列,但是在 Oracle 中,当转换为 DATE 列时,它将只具有日期部分。另一个例子是,DateTimeOffset 甚至在 Oracle 和其他应用程序中也有对等项,但在 SQL Server 2005 上没有。
* 一些等价类型略有不同。例如,在 SQL Server 中,dateTIME 属性可以转换为同时具有日期和时间部分的 DateTime 列,但是在 Oracle 中,当转换为 DATE 列时,它将只具有日期部分。另一个例子是,DateTimeOffset 甚至在 Oracle 和其他应用中也有对等项,但在 SQL Server 2005 上没有。
* 用于并发检查的 [TimestampAttribute](http://technet.microsoft.com/en-us/library/ms182776.aspx) 所隐含的 [ROWVERSION](http://technet.microsoft.com/en-us/library/ms182776.aspx) 类型,或者更好地说,它的工作方式,也只存在于 SQL Server 系列中。
* 浮点或十进制类型可能有不同的精度。
* 最后但同样重要的是,不要期望数据库生成能够工作:它不会工作,这意味着你只能靠自己。
......
......@@ -262,7 +262,7 @@ HttpContext 是巨大的。如果你需要伪造的不仅仅是对 HttpContext
## 伪造原则
到目前为止,我们已经了解了如何伪造`HttpContextBase``HttpRequestBase``HttpResponseBase``HttpSessionStateBase`。这涵盖了您将在 MVC 控制器中使用的大量代码类型,但是 MVC 应用程序中有一个很大的部分我们还没有谈到,那就是身份验证和授权。让我们看看如何在控制器的动作方法中单元测试使用`IPrincipal`的代码。
到目前为止,我们已经了解了如何伪造`HttpContextBase``HttpRequestBase``HttpResponseBase``HttpSessionStateBase`。这涵盖了您将在 MVC 控制器中使用的大量代码类型,但是 MVC 应用中有一个很大的部分我们还没有谈到,那就是身份验证和授权。让我们看看如何在控制器的动作方法中单元测试使用`IPrincipal`的代码。
| ![](img/note.png) | 注意:你可以在这里找到更多关于 IPrincipal [的信息。](https://msdn.microsoft.com/en-us/library/system.security.principal.iprincipal(v=vs.110).aspx) |
......
# 前言
# 零、前言
## 使用代码示例
这本书非常依赖代码示例来表达 F#概念。代码样本可在[https://bitbucket.org/syncfusion/fsharp-succinctly](https://bitbucket.org/syncfusion/fsharp-succinctly)获得。
这本书非常依赖代码示例来表达 F# 概念。代码样本可在[https://bitbucket.org/syncfusion/fsharp-succinctly](https://bitbucket.org/syncfusion/fsharp-succinctly)获得。
代码示例作为单独的 Visual Studio F#项目文件提供。样本按章节组织,并以各自章节的小标题命名。
代码示例作为单独的 Visual Studio F# 项目文件提供。样本按章节组织,并以各自章节的小标题命名。
大多数示例都是控制台应用程序。在 Visual Studio 中,如果以调试模式(F5)运行应用程序,控制台窗口会弹出并立即关闭。要查看样本结果,使用**启动**而不调试(Ctrl+F5)。这将在控制台应用程序的末尾添加一个*按任意键继续*提示,允许您通过按任意键关闭控制台窗口。
\ No newline at end of file
大多数示例都是控制台应用。在 Visual Studio 中,如果以调试模式(F5)运行应用,控制台窗口会弹出并立即关闭。要查看样本结果,使用**启动**而不调试(Ctrl+F5)。这将在控制台应用的末尾添加一个*按任意键继续*提示,允许您通过按任意键关闭控制台窗口。
\ No newline at end of file
# 第一章简介
# 一、简介
这一介绍性章节将解决一些你可能对 F#和函数式编程(FP)有疑问的主要问题。
这一介绍性章节将解决一些你可能对 F# 和函数式编程(FP)有疑问的主要问题。
## 什么是函数式编程?
纯函数式编程将所有程序视为接受参数和返回值的函数的集合。与命令式和面向对象编程不同,它不允许任何副作用,并且使用递归代替循环进行迭代。函数程序中的函数非常像数学函数,因为它们不会改变程序的状态。最简单地说,一旦一个值被赋给一个标识符,它就不会改变,函数也不会改变参数值,函数返回的结果是全新的值。在典型的底层实现中,一旦一个值被分配给内存中的某个区域,它就不会改变。为了创建结果,函数复制值,然后更改副本,留下原始值供其他函数自由使用,并最终在不再需要时丢弃。(这就是垃圾收集的想法起源的地方。)
纯函数式编程的数学基础是优雅的,因此 FP 为许多计算问题提供了漂亮、简洁的解决方案,但它的无状态和递归性质使其他范式便于处理许多常见的编程任务。然而,F#的一个很大的优势是,你可以使用多种范式,并将它们混合起来,以你认为最方便的方式解决问题。
纯函数式编程的数学基础是优雅的,因此 FP 为许多计算问题提供了漂亮、简洁的解决方案,但它的无状态和递归性质使其他范式便于处理许多常见的编程任务。然而,F# 的一个很大的优势是,你可以使用多种范式,并将它们混合起来,以你认为最方便的方式解决问题。
## 为什么函数式编程很重要?
......@@ -22,38 +22,38 @@
## 什么是 F#?
函数式编程是解决许多棘手计算问题的最佳方法,但纯 FP 通常不适合通用编程。正因为如此,FP 语言已经逐渐接受了命令式和 OO 范例的某些方面,保持了对 FP 范例的忠实,但是包含了轻松编写任何类型程序所需的特性。F#是这条道路上的天然接班人。它也不仅仅是一种 FP 语言。
函数式编程是解决许多棘手计算问题的最佳方法,但纯 FP 通常不适合通用编程。正因为如此,FP 语言已经逐渐接受了命令式和 OO 范例的某些方面,保持了对 FP 范例的忠实,但是包含了轻松编写任何类型程序所需的特性。F# 是这条道路上的天然接班人。它也不仅仅是一种 FP 语言。
一些最流行的函数式语言,包括 OCaml、Haskell、Lisp 和 Scheme,传统上都是使用定制运行时实现的,这导致了缺乏互操作性等问题。F#是一种通用编程语言。NET,一个通用运行时。F#平滑地集成了所有三种主要的编程范例。使用 F#,您可以选择最能有效解决问题的范式。如果你是一个纯粹主义者,你可以做纯函数式编程,但是你可以很容易地在同一个程序中结合函数式、命令式和面向对象的风格,并利用每种范式的优势。像其他类型化函数语言一样,F#是强类型化的,但也使用推断类型,因此程序员不需要花时间明确指定类型,除非存在歧义。此外,F#与无缝集成。NET 框架基类库。在 F#中使用 BCL 就像在 C#或 Visual Basic 中使用它一样简单(甚至可能更简单)。
一些最流行的函数式语言,包括 OCaml、Haskell、Lisp 和 Scheme,传统上都是使用定制运行时实现的,这导致了缺乏互操作性等问题。F# 是一种通用编程语言。NET,一个通用运行时。F# 平滑地集成了所有三种主要的编程范例。使用 F#,您可以选择最能有效解决问题的范式。如果你是一个纯粹主义者,你可以做纯函数式编程,但是你可以很容易地在同一个程序中结合函数式、命令式和面向对象的风格,并利用每种范式的优势。像其他类型化函数语言一样,F# 是强类型化的,但也使用推断类型,因此程序员不需要花时间明确指定类型,除非存在歧义。此外,F# 与无缝集成。NET 框架基类库。在 F# 中使用 BCL 就像在 C#或 Visual Basic 中使用它一样简单(甚至可能更简单)。
F#是以 Objective Caml (OCaml)为模型的,OCaml 是一种成功的面向对象的函数式编程语言,然后经过调整和扩展,在技术上和哲学上与. NET 很好地结合在一起。NET,并使用户能够做任何事情。NET 允许。F#编译器可以编译它所支持的公共语言基础设施的所有实现。NET 泛型,它甚至提供了内联中间语言代码。F#编译器不仅为任何命令行界面生成可执行文件,还可以在任何有命令行界面的环境下运行,这意味着 F#不限于 Windows,而是可以在 Linux、苹果的 OS X 和 iOS 以及谷歌的安卓操作系统上运行。
F# 是以 Objective Caml (OCaml)为模型的,OCaml 是一种成功的面向对象的函数式编程语言,然后经过调整和扩展,在技术上和哲学上与. NET 很好地结合在一起。NET,并使用户能够做任何事情。NET 允许。F# 编译器可以编译它所支持的公共语言基础设施的所有实现。NET 泛型,它甚至提供了内联中间语言代码。F# 编译器不仅为任何命令行界面生成可执行文件,还可以在任何有命令行界面的环境下运行,这意味着 F# 不限于 Windows,而是可以在 Linux、苹果的 OS X 和 iOS 以及谷歌的安卓操作系统上运行。
F# 2.0 编译器与 Visual Studio 2012、Visual Studio 2010 一起分发,并作为 Visual Studio 2008 的插件提供。它支持智能感知表达式完成和自动表达式检查。它还提供工具提示来显示已经为表达式推断了哪些类型。程序员经常评论说,这真的有助于将语言带入生活。F# 2.0 也有一个开源版本,根据 Apache 许可证授权,可从[http://github.com/fsharp](http://github.com/fsharp)获得。
F#首先由剑桥微软研究院(MSR)的唐·赛姆实现。该项目现已被华盛顿州雷德蒙的微软公司接受,编译器和 Visual Studio 集成的实现现已由位于剑桥和雷德蒙的团队开发。在撰写本文时,团队专注于实现 F# 3.0,它在 Visual Studio“dev 11”测试版中可用。
F# 首先由剑桥微软研究院(MSR)的唐·赛姆实现。该项目现已被华盛顿州雷德蒙的微软公司接受,编译器和 Visual Studio 集成的实现现已由位于剑桥和雷德蒙的团队开发。在撰写本文时,团队专注于实现 F# 3.0,它在 Visual Studio“dev 11”测试版中可用。
虽然其他 FP 语言运行在。NET,F#已经确立了自己作为事实上的。NET 函数式编程语言,因为它的实现质量及其与。NET 和 Visual Studio。
虽然其他 FP 语言运行在。NET,F# 已经确立了自己作为事实上的。NET 函数式编程语言,因为它的实现质量及其与。NET 和 Visual Studio。
没有其他的。NET 语言和 F#一样好用,一样灵活!
没有其他的。NET 语言和 F# 一样好用,一样灵活!
## 谁在用 F#?
F#在微软内部有着强大的影响力,无论是在 MSR 还是整个公司。拉尔夫·赫布里奇是 MSR 应用游戏集团的领导者,该集团专门研究机器学习技术,是 F#越来越多粉丝的典型代表:
F# 在微软内部有着强大的影响力,无论是在 MSR 还是整个公司。拉尔夫·赫布里奇是 MSR 应用游戏集团的领导者,该集团专门研究机器学习技术,是 F# 越来越多粉丝的典型代表:
第一个应用程序是解析分布在 300 多个目录中的 11,000 多个文本文件中的 110GB 日志数据,并将其导入到一个 SQL 数据库中。整个应用程序长达 90 行(包括注释!)并在 18 小时内完成了解析源文件和导入数据的任务;这样算下来,每秒钟要处理惊人的 10,000 个日志行!请注意,我根本没有优化代码,而是以最明显的方式编写了应用程序。我真的很惊讶,因为我计划了至少一周的时间来编写和运行应用程序
第一个应用是解析分布在 300 多个目录中的 11,000 多个文本文件中的 110GB 日志数据,并将其导入到一个 SQL 数据库中。整个应用长达 90 行(包括注释!)并在 18 小时内完成了解析源文件和导入数据的任务;这样算下来,每秒钟要处理惊人的 10,000 个日志行!请注意,我根本没有优化代码,而是以最明显的方式编写了应用。我真的很惊讶,因为我计划了至少一周的时间来编写和运行应用
第二个应用是对数百万条反馈的分析。我们已经开发了模型方程,我只是把它们作为 F#程序输入;加上从 SQL 数据库读取数据和将结果写入 MATLAB 数据文件,F#源代码有 100 行长(包括注释)。再次,我对运行时间感到惊讶;在一台标准的台式计算机上,数百万个数据项的整个处理过程需要 10 分钟。我的 C#参考应用程序(来自一些早期的任务)几乎有 1000 行长,速度也并不快。从开发模型方程到获得第一个真实世界的数据结果,整个工作花了两天时间。
第二个应用是对数百万条反馈的分析。我们已经开发了模型方程,我只是把它们作为 F# 程序输入;加上从 SQL 数据库读取数据和将结果写入 MATLAB 数据文件,F# 源代码有 100 行长(包括注释)。再次,我对运行时间感到惊讶;在一台标准的台式计算机上,数百万个数据项的整个处理过程需要 10 分钟。我的 C#参考应用(来自一些早期的任务)几乎有 1000 行长,速度也并不快。从开发模型方程到获得第一个真实世界的数据结果,整个工作花了两天时间。
拉尔夫·赫布里奇,微软研究院(http://blogs.msdn.com/dsyme/archive/2006/04/01/566301.aspx T2)
微软之外的 F#使用也在快速增长。我问了 Cyfeon Solutions 的 Chance Coble,关于 F#给他的工作带来了什么。
微软之外的 F# 使用也在快速增长。我问了 Cyfeon Solutions 的 Chance Coble,关于 F# 给他的工作带来了什么。
F#一遍又一遍地向我陈述它的理由。我决定尝试的第一个项目是机器视觉努力,它将从提交的指纹卡中识别和提取指纹,并将它们加载到生物识别系统中。项目计划是手动执行指纹提取,这变得越来越麻烦,自动化结果是一个巨大的胜利(用很少的代码)。后来我们决定将 F#工作包含在一个用 C#编写的更大的应用程序中,并轻松地完成了集成。从那以后,我在机器学习、特定领域语言设计、三维可视化、符号分析和任何需要高性能数据处理的项目中使用了 F#。能够轻松地将功能模块集成到现有的生产规模应用程序中,这使得 F#不仅很有趣,而且是项目领导的重要补充。用一个成熟而丰富的平台统一函数式编程。NET 开辟了大量的机会。
F# 一遍又一遍地向我陈述它的理由。我决定尝试的第一个项目是机器视觉努力,它将从提交的指纹卡中识别和提取指纹,并将它们加载到生物识别系统中。项目计划是手动执行指纹提取,这变得越来越麻烦,自动化结果是一个巨大的胜利(用很少的代码)。后来我们决定将 F# 工作包含在一个用 C#编写的更大的应用中,并轻松地完成了集成。从那以后,我在机器学习、特定领域语言设计、三维可视化、符号分析和任何需要高性能数据处理的项目中使用了 F#。能够轻松地将功能模块集成到现有的生产规模应用中,这使得 F# 不仅很有趣,而且是项目领导的重要补充。用一个成熟而丰富的平台统一函数式编程。NET 开辟了大量的机会。
Cyfeon Solutions 首席技术官 Chance Coble(私人电子邮件)
## 这本书是给谁的?
这本书主要面向想要在 F#上快速上手的 IT 专业人士。工作知识。NET 框架和一些 C#或 Visual Basic 的知识会很好,但这不是必需的。你真正需要的只是一些用任何语言编程的经验,这样你才能舒服地学习 F#。
这本书主要面向想要在 F# 上快速上手的 IT 专业人士。工作知识。NET 框架和一些 C#或 Visual Basic 的知识会很好,但这不是必需的。你真正需要的只是一些用任何语言编程的经验,这样你才能舒服地学习 F#。
即使是完全的初学者,他们以前从未编程过,并且正在学习 F#作为他们的第一种计算机语言,也应该会发现这本书非常易读。虽然它本身并不试图教授入门编程,但它确实仔细呈现了 F#的所有重要细节。
\ No newline at end of file
即使是完全的初学者,他们以前从未编程过,并且正在学习 F# 作为他们的第一种计算机语言,也应该会发现这本书非常易读。虽然它本身并不试图教授入门编程,但它确实仔细呈现了 F# 的所有重要细节。
\ No newline at end of file
# 第二章 F#的第一步
# 二、F# 的第一步
本章将重点介绍一些关于 F#语言及其编程环境的一般介绍性细节。接下来的三章将集中在充实语言的细节,而这一章将只是提供一个可以做的尝试。所以不要担心,如果你不理解本章中看到的例子的所有细节,本书的其余部分会把它们填满。
本章将重点介绍一些关于 F# 语言及其编程环境的一般介绍性细节。接下来的三章将集中在充实语言的细节,而这一章将只是提供一个可以做的尝试。所以不要担心,如果你不理解本章中看到的例子的所有细节,本书的其余部分会把它们填满。
## 获取并安装 F#
使用 F#最简单快捷的方法是使用微软的 Visual Studio。F#包含在 Visual Studio 2012 和 2010 中。如果没有 Visual Studio 的副本,可以从[http://www.microsoft.com/visualstudio/try](http://www.microsoft.com/visualstudio/try)下载 90 天免费试用版。
使用 F# 最简单快捷的方法是使用微软的 Visual Studio。F# 包含在 Visual Studio 2012 和 2010 中。如果没有 Visual Studio 的副本,可以从[http://www.microsoft.com/visualstudio/try](http://www.microsoft.com/visualstudio/try)下载 90 天免费试用版。
默认情况下,Visual Studio 2012 和 2010 都安装了 F#,所以只需安装带有默认选项的 Visual Studio 就足够了。如果您安装了 Visual Studio,但 F#不可用,则可能是在安装 Visual Studio 时停用了 F#。要激活 F#,打开**控制面板**,进入**程序**菜单。
默认情况下,Visual Studio 2012 和 2010 都安装了 F#,所以只需安装带有默认选项的 Visual Studio 就足够了。如果您安装了 Visual Studio,但 F# 不可用,则可能是在安装 Visual Studio 时停用了 F#。要激活 F#,打开**控制面板**,进入**程序**菜单。
如果你不想在 Visual Studio 中使用 F#的话,你可以在[http://www.microsoft.com/download/en/details.aspx?id=11100](http://www.microsoft.com/download/en/details.aspx?id=11100)从微软下载一个命令行编译器,用你喜欢的文本编辑器编辑 F#源文件。因为我认为 Visual Studio 是初学者体验 F#的最佳方式,所以本章的其余部分将假设您使用的是 Visual Studio,尽管所有示例都将与编译器的命令行版本一起工作。
如果你不想在 Visual Studio 中使用 F# 的话,你可以在[http://www.microsoft.com/download/en/details.aspx?id=11100](http://www.microsoft.com/download/en/details.aspx?id=11100)从微软下载一个命令行编译器,用你喜欢的文本编辑器编辑 F# 源文件。因为我认为 Visual Studio 是初学者体验 F# 的最佳方式,所以本章的其余部分将假设您使用的是 Visual Studio,尽管所有示例都将与编译器的命令行版本一起工作。
## 你好世界
按照惯例,让我们从 F#中的“hello world”节目开始。首先,我们需要创建一个 Visual Studio 项目来托管我们的程序。为此,导航至**文件** > **新建** > **项目……**并选择一个 **F#应用程序**
按照惯例,让我们从 F# 中的“hello world”节目开始。首先,我们需要创建一个 Visual Studio 项目来托管我们的程序。为此,导航至**文件** > **新建** > **项目……**并选择一个 **F# 应用**
| ![](img/note.png) | 注意:F#仅附带四个预安装的应用程序或库模板。然而,网上有更多的模板。这些在线模板由微软的 F#团队和 F#社区共同提供。它们可以通过 Visual Studio 的“新建项目”对话框进行搜索和安装。 |
| ![](img/note.png) | 注意:F# 仅附带四个预安装的应用或库模板。然而,网上有更多的模板。这些在线模板由微软的 F# 团队和 F# 社区共同提供。它们可以通过 Visual Studio 的“新建项目”对话框进行搜索和安装。 |
删除 **program.fs** 文件中的内容,并输入以下行:
......@@ -23,7 +23,7 @@
```
现在按 F5 编译并执行程序,您会看到控制台短暂弹出“Hello World”问候语。请注意程序只有一行长——这是 F#哲学的一部分,代码应该尽可能不受语法混乱的影响,您会发现这是许多函数式编程语言共有的哲学。我们只是希望能够调用`System.Console.WriteLine`方法并传递给它一个字符串,所以这是我们需要的程序的仅有的两个元素。
现在按 F5 编译并执行程序,您会看到控制台短暂弹出“Hello World”问候语。请注意程序只有一行长——这是 F# 哲学的一部分,代码应该尽可能不受语法混乱的影响,您会发现这是许多函数式编程语言共有的哲学。我们只是希望能够调用`System.Console.WriteLine`方法并传递给它一个字符串,所以这是我们需要的程序的仅有的两个元素。
因为程序在问候被写入控制台后直接退出,所以问候文本在屏幕上的时间可能太短,我们看不到。让我们通过从控制台读取一行来解决这个问题,以便程序在按下回车键之前不会退出:
......@@ -37,9 +37,9 @@
现在再次按下 F5 键。这次执行程序时,问候语会一直保留,直到您按回车键,程序退出。注意我们如何使用`open`关键字打开`System`命名空间。这允许我们从`Console`类名的开头移除`System`,编译器仍然能够找到该类,因为它现在将在`System`命名空间中寻找它。`open`关键字在用于导入名称空间时与 C#中的`using`关键字非常相似。
## 使用 F#交互
## 使用 F# 交互
Visual Studio 附带了一个名为 F# Interactive 的 F#交互版本。这有时被称为读取-评估-打印循环,简称 REPL。它给了 F#一种动态语言的感觉,因为程序员能够交互式地评估他或她的程序的各个部分,并立即看到结果,尽管应该注意的是,F# Interactive 动态编译您传递给它的代码部分,因此您应该看到与编译后的 F#代码相似的性能水平。要使用 F# Interactive,只需突出显示要评估的代码部分,然后按 Alt+Enter。然后,您将在通常位于屏幕底部的 F#交互式窗口中看到这段代码的打印结果。因此,如果我们突出显示最初的“hello world”程序并按 Alt+Enter,我们会看到以下结果:
Visual Studio 附带了一个名为 F# Interactive 的 F# 交互版本。这有时被称为读取-评估-打印循环,简称 REPL。它给了 F# 一种动态语言的感觉,因为程序员能够交互式地评估他或她的程序的各个部分,并立即看到结果,尽管应该注意的是,F# Interactive 动态编译您传递给它的代码部分,因此您应该看到与编译后的 F# 代码相似的性能水平。要使用 F# Interactive,只需突出显示要评估的代码部分,然后按 Alt+Enter。然后,您将在通常位于屏幕底部的 F# 交互式窗口中看到这段代码的打印结果。因此,如果我们突出显示最初的“hello world”程序并按 Alt+Enter,我们会看到以下结果:
你好世界
......@@ -47,13 +47,13 @@ Visual Studio 附带了一个名为 F# Interactive 的 F#交互版本。这有
第一行是输出到控制台的问候。第二个是关于程序类型的一些细节——暂时不要太担心这个。类型将在后面的章节中解释。
能够交互执行这样的代码是我最喜欢的 F#特性之一。我认为能够快速尝试这样的想法是一种真正的生产力提升。所以让我们继续看看你可以用 F# Interactive 做的一些其他事情,比如创建交互式图表。
能够交互执行这样的代码是我最喜欢的 F# 特性之一。我认为能够快速尝试这样的想法是一种真正的生产力提升。所以让我们继续看看你可以用 F# Interactive 做的一些其他事情,比如创建交互式图表。
F#团队已经为`System.Windows.​Forms.DataVisua​lization.Charti​ng.dll`创建了一个 F#友好的包装。这个包装器的主要目的是让您能够快速地将程序中可用的数据(或 F#交互会话)显示为图表。可从[http://code . msdn . Microsoft . com/windowsdesktop/fsharpchat-b 59073 F5](http://code.msdn.microsoft.com/windowsdesktop/FSharpChart-b59073f5)下载。
F# 团队已经为`System.Windows.​Forms.DataVisua​lization.Charti​ng.dll`创建了一个 F# 友好的包装。这个包装器的主要目的是让您能够快速地将程序中可用的数据(或 F# 交互会话)显示为图表。可从[http://code . msdn . Microsoft . com/windowsdesktop/fsharpchat-b 59073 F5](http://code.msdn.microsoft.com/windowsdesktop/FSharpChart-b59073f5)下载。
一旦你解压下载的 **FSharpChart** 文件夹,你会在 **F#** > **脚本**文件夹中找到 **FSharpChart.fsx** 文件。您需要确保该脚本与您正在使用的 F#脚本在同一个目录中,或者相应地修改脚本的路径。
一旦你解压下载的 **FSharpChart** 文件夹,你会在 **F#** > **脚本**文件夹中找到 **FSharpChart.fsx** 文件。您需要确保该脚本与您正在使用的 F# 脚本在同一个目录中,或者相应地修改脚本的路径。
现在让我们看看如何使用 F#图表。以下示例显示了如何创建显示简单直线的图表:
现在让我们看看如何使用 F# 图表。以下示例显示了如何创建显示简单直线的图表:
```fs
#load "FSharpChart.fsx"
......@@ -71,7 +71,7 @@ F#团队已经为`System.Windows.​Forms.DataVisua​lization.Charti​ng.dll`
图 1:F #交互中的折线图
让我们来看看这个程序是如何工作的。第一行将图表脚本(一个名为`FSharpChart.fsx`的文件)加载到 F#交互会话中。这一行可能需要几秒钟,因为图表脚本相当大,但您只需要加载一次,这些功能将继续在交互式会话中可用。下一行导入我们将要使用的图表函数的名称空间。下面一行创建一个整数列表,并将它们绑定到`data`标识符。最后,我们将我们的列表传递给制图功能`FSharpChart.Line`,它会绘制一个线形图。这不是世界上最令人兴奋的图表,让我们再看一张。
让我们来看看这个程序是如何工作的。第一行将图表脚本(一个名为`FSharpChart.fsx`的文件)加载到 F# 交互会话中。这一行可能需要几秒钟,因为图表脚本相当大,但您只需要加载一次,这些功能将继续在交互式会话中可用。下一行导入我们将要使用的图表函数的名称空间。下面一行创建一个整数列表,并将它们绑定到`data`标识符。最后,我们将我们的列表传递给制图功能`FSharpChart.Line`,它会绘制一个线形图。这不是世界上最令人兴奋的图表,让我们再看一张。
下面的代码示例将创建一个柱形图,显示日期和每个日期的值:
......@@ -97,7 +97,7 @@ F#团队已经为`System.Windows.​Forms.DataVisua​lization.Charti​ng.dll`
程序的顶部,加载 **FSharpChart.fsx** 脚本和`open`语句的部分与之前基本相同。第一个主要区别是我们定义了一个函数`dateInApril`,提供了一种在 2012 年 4 月创建`DateTime`对象的简写方式。接下来,您会注意到我们的数据列表不是单个值,而是成对的值,称为*元组*。每对包含一个日期对象和一个整数。最后,我们将元组列表传递给绘制柱形图的制图功能`FSharpChart.` `Column`。虽然这个图表可能比上一个图表有趣一点,但这个例子并不太现实,因为我们更有可能绘制来自外部数据源(如文本文件)的数据。
让我们看看如何从. csv 文件中加载一些数据并用 F#绘制图表:
让我们看看如何从. csv 文件中加载一些数据并用 F# 绘制图表:
```fs
#load "FSharpChart.fsx"
......@@ -122,4 +122,4 @@ F#团队已经为`System.Windows.​Forms.DataVisua​lization.Charti​ng.dll`
## 总结
这一章已经非常简要地介绍了使用 F#来创建编译程序和使用 F# Interactive 来快速测试想法。本书的剩余部分将详细介绍 F#语言的语法和特性,从而指导如何用 F #编程。
\ No newline at end of file
这一章已经非常简要地介绍了使用 F# 来创建编译程序和使用 F# Interactive 来快速测试想法。本书的剩余部分将详细介绍 F# 语言的语法和特性,从而指导如何用 F #编程。
\ No newline at end of file
此差异已折叠。
# 第四章类型和类型推断
# 四、类型和类型推断
F#是一种*强类型*语言,这意味着你不能使用一个值不合适的函数。不能调用以字符串作为参数并带有整数参数的函数;您必须在两者之间显式转换。这种语言对待其价值类型的方式被称为其*类型系统*。F#有一个不会妨碍常规编程的类型系统。在 F#中,所有值都有一个类型,这包括作为函数的值。
F# 是一种*强类型*语言,这意味着你不能使用一个值不合适的函数。不能调用以字符串作为参数并带有整数参数的函数;您必须在两者之间显式转换。这种语言对待其价值类型的方式被称为其*类型系统*。F# 有一个不会妨碍常规编程的类型系统。在 F# 中,所有值都有一个类型,这包括作为函数的值。
## 类型推断
通常,您不需要显式声明类型;编译器将从函数中文字的类型和它调用的其他函数的结果类型中计算出一个值的类型。如果一切正常,编译器会将类型保留给自己;只有当存在类型不匹配时,编译器才会通过报告编译错误来通知您。这个过程一般被称为*式推理*。如果你想更多地了解程序中的类型,可以用`–i`开关让编译器显示所有推断的类型。Visual Studio 用户将鼠标指针悬停在标识符上时,会获得显示类型的工具提示。
类型推断在 F#中的工作方式相当容易理解。编译器在整个程序中工作,在定义标识符时为它们分配类型,从最左边的标识符开始,一直向下到最右边的标识符。它根据已经知道的类型分配类型,也就是文字的类型和(更常见的)在其他源文件或程序集中定义的函数的类型。
类型推断在 F# 中的工作方式相当容易理解。编译器在整个程序中工作,在定义标识符时为它们分配类型,从最左边的标识符开始,一直向下到最右边的标识符。它根据已经知道的类型分配类型,也就是文字的类型和(更常见的)在其他源文件或程序集中定义的函数的类型。
下一个例子定义了两个 F#标识符,然后用 F#编译器的`–i`开关在控制台上显示它们的推断类型。
下一个例子定义了两个 F# 标识符,然后用 F# 编译器的`–i`开关在控制台上显示它们的推断类型。
```fs
let aString = "Spring time in Paris"
......@@ -34,7 +34,7 @@ val makeMessage : int ->字符串
val half : int -> int
注意`makeMessage`函数的定义前缀是关键字`val`,就像你之前看到的两个值一样;即使它是一个函数,F#编译器仍然认为它是一个值。此外,类型本身使用符号`int -> string`,这意味着一个函数接受一个整数并返回一个字符串。类型名称之间的`->` (ASCII 箭头)表示正在应用的函数的转换。箭头表示值的转换,但不一定表示类型,因为它可以表示将值转换为相同类型值的函数,如第二行的`half`函数所示。
注意`makeMessage`函数的定义前缀是关键字`val`,就像你之前看到的两个值一样;即使它是一个函数,F# 编译器仍然认为它是一个值。此外,类型本身使用符号`int -> string`,这意味着一个函数接受一个整数并返回一个字符串。类型名称之间的`->` (ASCII 箭头)表示正在应用的函数的转换。箭头表示值的转换,但不一定表示类型,因为它可以表示将值转换为相同类型值的函数,如第二行的`half`函数所示。
可以部分应用的函数类型和接受元组的函数类型不同。以下功能`div1``div2`说明了这一点。
......@@ -63,9 +63,9 @@ val divremainder:int-> int-> int * int
瓦尔·多诺西:“a->”a
该函数的类型为`'a -> 'a`,即取一个类型的值,返回一个相同类型的值。任何以单引号(`'`)开头的类型都意味着一个*变量*类型。F#有一个类型`obj`,它映射到`System.Object`并代表任何类型的值——这个概念你可能会从其他基于公共语言运行时(CLR)的编程语言中熟悉(事实上,许多语言并不以 CLR 为目标)。但是,变量类型不一样。请注意该类型在箭头的两侧有一个`'a`。这意味着,即使编译器还不知道类型,它也知道返回值的类型将与参数的类型相同。类型系统的这一特性,有时被称为*类型参数化*,允许编译器在编译时发现更多的类型错误,并有助于避免强制转换。
该函数的类型为`'a -> 'a`,即取一个类型的值,返回一个相同类型的值。任何以单引号(`'`)开头的类型都意味着一个*变量*类型。F# 有一个类型`obj`,它映射到`System.Object`并代表任何类型的值——这个概念你可能会从其他基于公共语言运行时(CLR)的编程语言中熟悉(事实上,许多语言并不以 CLR 为目标)。但是,变量类型不一样。请注意该类型在箭头的两侧有一个`'a`。这意味着,即使编译器还不知道类型,它也知道返回值的类型将与参数的类型相同。类型系统的这一特性,有时被称为*类型参数化*,允许编译器在编译时发现更多的类型错误,并有助于避免强制转换。
| ![](img/note.png) | 注意:变量类型或类型参数化的概念与*泛型*的概念密切相关,后者是在 CLR 2.0 版本中引入的,现在已经成为 CLI 2.0 版本的 ECMA 规范的一部分。当 F#以启用了泛型的 CLI 为目标时,它会通过在找到未确定类型的任何地方使用它们来充分利用它们。F#的创建者 Don Syme 在。NET CLR 在他开始研究 F#之前。有人可能会想推断他这么做是为了创造 F#! |
| ![](img/note.png) | 注意:变量类型或类型参数化的概念与*泛型*的概念密切相关,后者是在 CLR 2.0 版本中引入的,现在已经成为 CLI 2.0 版本的 ECMA 规范的一部分。当 F# 以启用了泛型的 CLI 为目标时,它会通过在找到未确定类型的任何地方使用它们来充分利用它们。F# 的创建者 Don Syme 在。NET CLR 在他开始研究 F# 之前。有人可能会想推断他这么做是为了创造 F#! |
下一个示例中显示的函数`doNothingToAnInt`是一个被约束的值的例子——一个*类型的约束*。在这种情况下,功能参数`x`被约束为`int`。可以将任何标识符约束为某种类型,而不仅仅是函数参数,尽管更典型的是需要约束参数。这里的列表`stringList`显示了如何约束不是函数参数的标识符。
......@@ -87,13 +87,13 @@ val stringList:字符串列表
`intList`值是整数列表,标识符的类型是`int list`。这表明编译器已经识别出列表只包含整数,在这种情况下,其项目的类型不是未确定的,而是`int`。除了类型为`int`的值之外,任何向列表中添加任何内容的尝试都将导致编译错误。
标识符`stringList`有类型标注。虽然这是不必要的,因为编译器可以从值解析类型,但它用于显示处理未确定类型的替代语法。您可以将该类型放在与其关联的类型之后的尖括号之间,而不只是将其写在类型名称之前。请注意,即使`stringList`的类型被限制为`list<string>`(字符串列表),编译器在显示类型时仍然将其类型报告为`string list`,它们的含义完全相同。支持此语法以使带有类型参数的 F#类型看起来像其他类型的泛型类型。NET 库。
标识符`stringList`有类型标注。虽然这是不必要的,因为编译器可以从值解析类型,但它用于显示处理未确定类型的替代语法。您可以将该类型放在与其关联的类型之后的尖括号之间,而不只是将其写在类型名称之前。请注意,即使`stringList`的类型被限制为`list<string>`(字符串列表),编译器在显示类型时仍然将其类型报告为`string list`,它们的含义完全相同。支持此语法以使带有类型参数的 F# 类型看起来像其他类型的泛型类型。NET 库。
在编写纯 F#时,约束值通常不是必需的,尽管它偶尔会有用。使用时最有用。NET 库,用 F#以外的语言编写,用于与非托管库进行互操作。在这两种情况下,编译器的类型信息较少,因此通常需要给它足够的信息来消除值的歧义。
在编写纯 F# 时,约束值通常不是必需的,尽管它偶尔会有用。使用时最有用。NET 库,用 F# 以外的语言编写,用于与非托管库进行互操作。在这两种情况下,编译器的类型信息较少,因此通常需要给它足够的信息来消除值的歧义。
## 定义类型
F#中的类型系统提供了许多定义自定义类型的功能。所有 F#的类型定义都分为两类:
F# 中的类型系统提供了许多定义自定义类型的功能。所有 F# 的类型定义都分为两类:
* *元组**记录*,它们是组成复合类型的一组类型(类似于 C 中的结构或 C#中的类)。
* *求和*类型,有时称为*联合*类型。
......@@ -109,7 +109,7 @@ F#中的类型系统提供了许多定义自定义类型的功能。所有 F#的
```
元组不同于 F#中大多数用户定义的类型,因为您不需要使用`type`关键字显式声明它们。要定义类型,您可以使用`type`关键字,后跟类型名称、等号,然后是您正在定义的类型。在最简单的形式中,您可以使用它为任何现有类型(包括元组)提供别名。给单个类型赋予别名通常并不有用,但是给元组赋予别名可能非常有用,尤其是当您想要使用元组作为类型约束时。下一个示例显示了如何为单个类型和元组赋予别名,以及如何使用别名作为类型约束。
元组不同于 F# 中大多数用户定义的类型,因为您不需要使用`type`关键字显式声明它们。要定义类型,您可以使用`type`关键字,后跟类型名称、等号,然后是您正在定义的类型。在最简单的形式中,您可以使用它为任何现有类型(包括元组)提供别名。给单个类型赋予别名通常并不有用,但是给元组赋予别名可能非常有用,尤其是当您想要使用元组作为类型约束时。下一个示例显示了如何为单个类型和元组赋予别名,以及如何使用别名作为类型约束。
```fs
type Name = string
......@@ -150,7 +150,7 @@ F#中的类型系统提供了许多定义自定义类型的功能。所有 F#的
将字段定义放在大括号之间,并用分号分隔。字段定义由后跟冒号的字段名称和字段类型组成。类型定义`Organization1`是字段名称唯一的记录类型。这意味着您可以使用简单的语法来创建这种类型的实例,在创建时不需要提及类型名称。要创建记录,您需要将字段名称后跟等号,并将字段值放在大括号(`{}`)之间,如`Rainbow`标识符所示。
F#不强制字段名是唯一的,所以有时编译器不能仅从字段名推断字段的类型。在这种情况下,编译器无法推断记录的类型。要创建具有非唯一字段的记录,编译器需要静态地知道正在创建的记录的类型。如果编译器无法推断记录的类型,您需要使用类型注释,如[类型推断](#_Type_Inference)部分所述。使用类型注释由类型`Organization2``Organization3`以及它们的实例`thePlayers``wayneManor`来说明。您可以看到在其名称后面显式给出的标识符的类型。
F# 不强制字段名是唯一的,所以有时编译器不能仅从字段名推断字段的类型。在这种情况下,编译器无法推断记录的类型。要创建具有非唯一字段的记录,编译器需要静态地知道正在创建的记录的类型。如果编译器无法推断记录的类型,您需要使用类型注释,如[类型推断](#_Type_Inference)部分所述。使用类型注释由类型`Organization2``Organization3`以及它们的实例`thePlayers``wayneManor`来说明。您可以看到在其名称后面显式给出的标识符的类型。
访问记录中的字段相当简单。您只需使用语法`record`标识符名称,后跟一个点,后跟字段名称。下面的例子说明了这一点,展示了如何访问`Organization`记录的`chief`字段。
......@@ -168,7 +168,7 @@ F#不强制字段名是唯一的,所以有时编译器不能仅从字段名推
```
默认情况下,记录是不可变的。对于一个命令式程序员来说,这听起来好像记录不是很有用,因为不可避免地会出现需要更改字段值的情况。为此,F#提供了一种简单的语法,用于创建具有更新字段的记录副本。要创建记录的副本,请将该记录的名称放在大括号中,后跟关键字`with`,然后是要用其更新值进行更改的字段列表。这样做的好处是,您不需要重新键入未更改的字段列表。下面的示例演示了这种方法。它创建了`wayneManor`的初始版本,然后创建了`wayneManor'`,其中`"Robin"`已经被移除。
默认情况下,记录是不可变的。对于一个命令式程序员来说,这听起来好像记录不是很有用,因为不可避免地会出现需要更改字段值的情况。为此,F# 提供了一种简单的语法,用于创建具有更新字段的记录副本。要创建记录的副本,请将该记录的名称放在大括号中,后跟关键字`with`,然后是要用其更新值进行更改的字段列表。这样做的好处是,您不需要重新键入未更改的字段列表。下面的示例演示了这种方法。它创建了`wayneManor`的初始版本,然后创建了`wayneManor'`,其中`"Robin"`已经被移除。
```fs
// Define an organization type.
......@@ -316,7 +316,7 @@ wayneManor ' = { chief = "蝙蝠侠";
```
这个问题的另一个解决方案是使用 F#的度量单位,它允许将类型应用于数值。
这个问题的另一个解决方案是使用 F# 的度量单位,它允许将类型应用于数值。
## 带类型参数的类型定义
......@@ -374,4 +374,4 @@ wayneManor ' = { chief = "蝙蝠侠";
## 总结
这是对如何在 F#中创建类型的简单介绍。你会发现 F#的类型系统提供了一种灵活的方式来表示程序中的数据。
\ No newline at end of file
这是对如何在 F# 中创建类型的简单介绍。你会发现 F# 的类型系统提供了一种灵活的方式来表示程序中的数据。
\ No newline at end of file
# 第五章面向对象编程
# 五、面向对象编程
面向对象编程是第三种主要的编程范式。有一种倾向是试图将功能范式和面向对象范式显示为相互竞争的,但我相信它们是互补的技术,可以很好地协同工作,我将在本章中尝试演示这一点。在本质上,面向对象编程有一些简单的思想,有时被称为面向对象编程的原则:封装、多态和继承。
可能最重要的原则是*封装*—实现和状态应该是*封装*的想法,或者隐藏在定义良好的边界之后。这使得程序的结构更容易管理。在 F#中,通过使用模块和类型定义的签名,以及通过简单地将它们本地定义到表达式或类构造中,您可以隐藏一些东西(您将在本章中看到这两者的示例)。
可能最重要的原则是*封装*—实现和状态应该是*封装*的想法,或者隐藏在定义良好的边界之后。这使得程序的结构更容易管理。在 F# 中,通过使用模块和类型定义的签名,以及通过简单地将它们本地定义到表达式或类构造中,您可以隐藏一些东西(您将在本章中看到这两者的示例)。
第二个原则,*多态性*,是您可以用多种方式实现抽象实体的想法。您已经遇到了许多简单的抽象实体,例如函数类型。函数类型是抽象的,因为您可以用许多不同的方式实现具有特定类型的函数。例如,您可以将函数类型`int -> int`实现为给定参数递增的函数、参数递减的函数或数百万个数学序列中的任何一个。您还可以从现有的抽象组件中构建其他抽象实体,例如。NET 密件抄送。您还可以使用用户定义的接口类型来建模更复杂的抽象实体。接口类型的优点是可以分层排列;这叫*接口继承*。例如。NET BCL 包括集合类型的分层分类,在`System.Collections``System.Collections.Generic`名称空间中可用。
在 OOP 中,您有时可以分层排列实现片段。这被称为*实现继承*,在 F#编程中它往往不那么重要,因为函数式编程为定义和共享实现片段提供了灵活性。然而,它对于诸如图形用户界面(GUI)编程之类的领域是有意义的。
在 OOP 中,您有时可以分层排列实现片段。这被称为*实现继承*,在 F# 编程中它往往不那么重要,因为函数式编程为定义和共享实现片段提供了灵活性。然而,它对于诸如图形用户界面(GUI)编程之类的领域是有意义的。
虽然面向对象编程的原则很重要,但面向对象编程也已经成为围绕系统的值组织代码的代名词*名词*,然后提供对这些值的操作,作为对该值进行操作的成员、函数或方法。这通常就像取一个以函数应用于某个值的样式编写的函数(如`String.length s`)并用点符号重写它(如`s.Length`)一样简单。这个简单的动作通常可以让你的代码更加清晰。在本章中,您将看到 F#如何允许您将成员附加到它的任何类型,而不仅仅是它的类,如果您愿意的话,使您能够以面向对象的方式组织您的所有代码。
虽然面向对象编程的原则很重要,但面向对象编程也已经成为围绕系统的值组织代码的代名词*名词*,然后提供对这些值的操作,作为对该值进行操作的成员、函数或方法。这通常就像取一个以函数应用于某个值的样式编写的函数(如`String.length s`)并用点符号重写它(如`s.Length`)一样简单。这个简单的动作通常可以让你的代码更加清晰。在本章中,您将看到 F# 如何允许您将成员附加到它的任何类型,而不仅仅是它的类,如果您愿意的话,使您能够以面向对象的方式组织您的所有代码。
F#提供了丰富的面向对象编程模型,允许您创建行为类似于 C#和 VB.NET 创建的类、接口和对象。也许更重要的是,当打包到库中并由该库的用户查看时,您在 F#中创建的类与用其他语言创建的类是无法区分的。然而,面向对象编程不仅仅是简单地定义对象,当您开始研究如何使用 F#本机类型以面向对象的方式编程时,您将会看到这一点。
F# 提供了丰富的面向对象编程模型,允许您创建行为类似于 C#和 VB.NET 创建的类、接口和对象。也许更重要的是,当打包到库中并由该库的用户查看时,您在 F# 中创建的类与用其他语言创建的类是无法区分的。然而,面向对象编程不仅仅是简单地定义对象,当您开始研究如何使用 F# 本机类型以面向对象的方式编程时,您将会看到这一点。
## 带成员的 F#类型
## 带成员的 F# 类型
可以向 F#的记录和联合类型添加函数。您可以使用点标记法调用添加到记录或联合类型的函数,就像您可以从非 F#编写的库中调用类的成员一样。当您想要向其他人公开您在 F#中定义的类型时,它也证明是有用的。NET 语言。许多程序员更喜欢看到对实例值的函数调用,这种技术为所有 F#类型提供了一种很好的方法。
可以向 F# 的记录和联合类型添加函数。您可以使用点标记法调用添加到记录或联合类型的函数,就像您可以从非 F# 编写的库中调用类的成员一样。当您想要向其他人公开您在 F# 中定义的类型时,它也证明是有用的。NET 语言。许多程序员更喜欢看到对实例值的函数调用,这种技术为所有 F# 类型提供了一种很好的方法。
定义带有成员的 F#记录或联合类型的语法与您在[第 4 章](04.html#_Chapter_4_)中学习的语法相同,除了这里它包括总是出现在最后的成员定义,在`with`关键字之后。成员本身的定义以关键字`member`开始,后面跟着一个标识符,该标识符代表成员被附加到的类型的参数,后面跟着一个点、函数名,然后是函数采用的任何其他参数。在这之后是等号后面是函数定义,可以是任何 F#表达式。
定义带有成员的 F# 记录或联合类型的语法与您在[第 4 章](04.html#_Chapter_4_)中学习的语法相同,除了这里它包括总是出现在最后的成员定义,在`with`关键字之后。成员本身的定义以关键字`member`开始,后面跟着一个标识符,该标识符代表成员被附加到的类型的参数,后面跟着一个点、函数名,然后是函数采用的任何其他参数。在这之后是等号后面是函数定义,可以是任何 F# 表达式。
以下示例定义了记录类型`Point`。它有两个字段,`Left``Top`;和成员函数`Swap``Swap`函数是一个简单的函数,用交换的`Left``Top`的值创建一个新点。注意如何在函数定义中使用在函数名`Swap`之前给出的`x`参数来访问记录的其他成员:
......@@ -76,7 +76,7 @@ F#提供了丰富的面向对象编程模型,允许您创建行为类似于 C#
```
调用函数的值作为参数传递给函数。当您考虑到函数需要能够访问调用它的值的字段和方法时,这是合乎逻辑的。有些 OO 语言对此使用特定的关键字,例如`this``Me`,但是在这种情况下,F#允许您通过在关键字成员— `x`之后指定名称来选择该参数的名称。
调用函数的值作为参数传递给函数。当您考虑到函数需要能够访问调用它的值的字段和方法时,这是合乎逻辑的。有些 OO 语言对此使用特定的关键字,例如`this``Me`,但是在这种情况下,F# 允许您通过在关键字成员— `x`之后指定名称来选择该参数的名称。
联合类型也可以有成员函数。定义它们的方式与定义记录类型的方式相同。下一个示例显示了一个联合类型`DrinkAmount`,其中添加了一个函数:
......@@ -106,11 +106,11 @@ F#提供了丰富的面向对象编程模型,允许您创建行为类似于 C#
茶:2
注意这是如何使用关键字`override`代替关键字`member`的。这具有替换或*覆盖*基本类型的现有功能的效果。对于与 F#类型相关联的函数成员来说,这不是一个很常见的做法,因为只有四种方法可以被覆盖:`ToString``Equals``GetHashCode``Finalize`。每一个。NET 类型从`System.Object`继承了这些。由于这些方法中的一些与 CLR 交互的方式,我唯一建议覆盖的是`ToString`。只有四种方法可用于重写,因为记录和联合类型不能作为基类或派生类,所以您不能继承方法来重写(从`System.Object`开始除外)。
注意这是如何使用关键字`override`代替关键字`member`的。这具有替换或*覆盖*基本类型的现有功能的效果。对于与 F# 类型相关联的函数成员来说,这不是一个很常见的做法,因为只有四种方法可以被覆盖:`ToString``Equals``GetHashCode``Finalize`。每一个。NET 类型从`System.Object`继承了这些。由于这些方法中的一些与 CLR 交互的方式,我唯一建议覆盖的是`ToString`。只有四种方法可用于重写,因为记录和联合类型不能作为基类或派生类,所以您不能继承方法来重写(从`System.Object`开始除外)。
## 定义类别
您已经看到了很多使用。NET 密件库;接下来,您将学习如何定义自己的类。在面向对象编程中,一个类应该对您正在创建的程序或库中使用的一些概念进行建模。例如,`String`模拟一组字符,`Process`类模拟一个操作系统进程。
您已经看到了很多使用。NET 密件库;接下来,您将学习如何定义自己的类。在面向对象编程中,一个类应该对您正在创建的程序或库中使用的一些概念进行建模。例如,`String`仿真一组字符,`Process`类仿真一个操作系统进程。
类是一种类型,因此类定义以`type`关键字开始,后面是类的名称和类的构造函数的参数(位于括号之间)。接下来是等号,后面是类的成员定义。类中最基本的成员叫做*方法*,这是一个可以访问类参数的函数。
......@@ -178,7 +178,7 @@ F#提供了丰富的面向对象编程模型,允许您创建行为类似于 C#
请注意成员如何访问类“`let`绑定,以及成员`GetFullName`如何返回预先计算的`fullName`值。
通常需要能够在类中改变值。例如,您可能需要在`User`类中提供`ChangePassword`方法来重置用户的密码。F#为您提供了两种方法来实现这一点。您可以使对象不可变——在这种情况下,您可以复制对象的参数,同时更改适当的值。这种方法通常被认为更适合函数式编程,但是如果对象有很多参数或者创建成本很高,就会有点不方便。例如,这样做可能计算成本很高,或者可能需要大量的输入/输出来构建它。以下示例说明了这种方法。请注意,在`ChangePassword`方法中,您如何调用`password`参数上的`hash`函数,将此函数与用户名一起传递给`User`对象的构造函数:
通常需要能够在类中改变值。例如,您可能需要在`User`类中提供`ChangePassword`方法来重置用户的密码。F# 为您提供了两种方法来实现这一点。您可以使对象不可变——在这种情况下,您可以复制对象的参数,同时更改适当的值。这种方法通常被认为更适合函数式编程,但是如果对象有很多参数或者创建成本很高,就会有点不方便。例如,这样做可能计算成本很高,或者可能需要大量的输入/输出来构建它。以下示例说明了这种方法。请注意,在`ChangePassword`方法中,您如何调用`password`参数上的`hash`函数,将此函数与用户名一起传递给`User`对象的构造函数:
```fs
// A class that represents a user.
......@@ -316,7 +316,7 @@ F#提供了丰富的面向对象编程模型,允许您创建行为类似于 C#
```
这是必要的,因为接口是在 F#中显式实现的。在使用方法`GetLogonMessage`之前,您必须有一个类型为`IUser`的标识符,而不仅仅是实现`IUser`的类的标识符。在示例的最后,您将以不同的方式解决这个问题。功能`logon`采用`IUser`类型的参数:
这是必要的,因为接口是在 F# 中显式实现的。在使用方法`GetLogonMessage`之前,您必须有一个类型为`IUser`的标识符,而不仅仅是实现`IUser`的类的标识符。在示例的最后,您将以不同的方式解决这个问题。功能`logon`采用`IUser`类型的参数:
```fs
let logon (iuser: IUser) =
......@@ -327,7 +327,7 @@ F#提供了丰富的面向对象编程模型,允许您创建行为类似于 C#
## 铸造
强制转换是一种通过丢弃信息来显式改变值的静态类型的方式,称为*向上强制转换*;或者重新发现它,这就是众所周知的*下降*。在 F#中,上转换和下转换有自己的运算符。类型层次结构从顶部的`obj`(或`System.Object`)开始,其所有后代都在它下面。向上转换将类型在层次结构中上移,而向下转换将类型在层次结构中下移。
强制转换是一种通过丢弃信息来显式改变值的静态类型的方式,称为*向上强制转换*;或者重新发现它,这就是众所周知的*下降*。在 F# 中,上转换和下转换有自己的运算符。类型层次结构从顶部的`obj`(或`System.Object`)开始,其所有后代都在它下面。向上转换将类型在层次结构中上移,而向下转换将类型在层次结构中下移。
上转换将值的静态类型更改为其祖先类型之一。这是安全的操作。编译器总是能够判断一个上转换是否会工作,因为它总是知道一个类型的所有祖先,所以它能够使用静态分析来确定一个上转换是否会成功。向上转换由冒号表示,后跟大于号(`:>`)。以下代码向您展示了如何使用上转换将`string`转换为`obj`:
......@@ -380,4 +380,4 @@ F#提供了丰富的面向对象编程模型,允许您创建行为类似于 C#
## 总结
您现在已经看到了如何在 F#中使用三种主要编程范例中的两种,以及 F#在任何混合风格的编码中有多灵活。
\ No newline at end of file
您现在已经看到了如何在 F# 中使用三种主要编程范例中的两种,以及 F# 在任何混合风格的编码中有多灵活。
\ No newline at end of file
此差异已折叠。
此差异已折叠。
# 第 8 章创建应用程序
# 八、创建应用
在这一章中,我想展示用 F#编写一个应用程序涉及到什么。对于我们将要实现的东西来说,“应用程序”可能是一个过于宏大的词,但重点是展示 F#与其他技术和框架的交互方式,就像你要创建一个真实世界的应用程序一样。
在这一章中,我想展示用 F# 编写一个应用涉及到什么。对于我们将要实现的东西来说,“应用”可能是一个过于宏大的词,但重点是展示 F# 与其他技术和框架的交互方式,就像你要创建一个真实世界的应用一样。
我们将在 HTML 网页中创建一个自动完成下拉列表。想法是输入你感兴趣的村庄、城镇或城市,自动完成功能将帮助你在系统中找到正确的。我们将使用 RavenDB 作为我们的数据存储,使用 PicoMvc 作为 Mvc 网络框架来处理应用层。PicoMvc 是我专门为 F#创建的一个 Mvc 框架。它很大程度上是受 OpenRasta、FubuMvc 和一点点 ASP.NET MVC 的启发,所以如果您不喜欢使用 PicoMvc,这里给出的例子可能很容易移植到这些框架中的任何一个。RavenDB 是一个用 C#实现的 NoSQL 数据库。我喜欢这个数据库,不是因为它速度快,并且通过分片为可伸缩性提供了很好的支持,这是毫无疑问的,而是因为它的实现者真正关注的是让开发人员非常容易使用它。
我们将在 HTML 网页中创建一个自动完成下拉列表。想法是输入你感兴趣的村庄、城镇或城市,自动完成功能将帮助你在系统中找到正确的。我们将使用 RavenDB 作为我们的数据存储,使用 PicoMvc 作为 Mvc 网络框架来处理应用层。PicoMvc 是我专门为 F# 创建的一个 Mvc 框架。它很大程度上是受 OpenRasta、FubuMvc 和一点点 ASP.NET MVC 的启发,所以如果您不喜欢使用 PicoMvc,这里给出的例子可能很容易移植到这些框架中的任何一个。RavenDB 是一个用 C#实现的 NoSQL 数据库。我喜欢这个数据库,不是因为它速度快,并且通过分片为可伸缩性提供了很好的支持,这是毫无疑问的,而是因为它的实现者真正关注的是让开发人员非常容易使用它。
如今,在 HTML 表单中创建自动完成下拉列表已经相当普遍了,有一个很好的 jQuery 插件可以处理 UI 方面的事情。将数据加载到 RavenDB 中,然后公开一个服务,该服务将返回与用户搜索相对应的 JSON 记录,这将是本章的重点。
......@@ -18,7 +18,7 @@
**Common** 项目包含我们的类型的定义,这些类型将存储在 RavenDB 中。通用项目将参考**负载社区****网络**项目。**加载社区**项目将包含将数据加载到 RavenDB 的 ETL 逻辑。**网页**项目将包含驱动网页的逻辑。 **WebHost** 项目是一个 c#“web 项目”——它只是为了保存项目的 HTML 部分,并使启动 web 服务器进行调试变得更容易。
现在项目已经建立到我们满意的程度,是时候看看应用程序的 ETL(提取、转换和加载)部分的一些实际代码了。
现在项目已经建立到我们满意的程度,是时候看看应用的 ETL(提取、转换和加载)部分的一些实际代码了。
## 提取/转换/加载
......@@ -82,7 +82,7 @@
现在我们在 RavenDB 中有了数据,我们希望能够向用户显示数据。为此,我们需要创建一个服务,将 JSON 文档返回给客户端。用 PicoMvc 和 RavenDB 实现服务很简单,但是要实现它,我们需要配置 PicoMvc 并在 RavenDB 中创建一个索引,以便我们可以查询它。
PicoMvc 旨在将 F#函数映射到 URL 和 HTTP 动词。这个想法是,基本框架独立于 web 服务器和主机平台,但是我们提供了钩子,允许您将 PicoMvc 插入现有平台。目前,唯一存在的钩子是将 PicoMvc 插入 ASP.NET 平台,这是通过一个名为`PicoMvcRouteHandler`的类来完成的,它是一个 ASP.NET 路由处理器。这个想法是,您向 ASP.NET 运行时注册这个路由处理程序,它提供了所有的管道,用于将 ASP.NET HTTP 处理程序将接收的调用和请求映射到您通过 PicoMvc 定义的处理程序函数。
PicoMvc 旨在将 F# 函数映射到 URL 和 HTTP 动词。这个想法是,基本框架独立于 web 服务器和主机平台,但是我们提供了钩子,允许您将 PicoMvc 插入现有平台。目前,唯一存在的钩子是将 PicoMvc 插入 ASP.NET 平台,这是通过一个名为`PicoMvcRouteHandler`的类来完成的,它是一个 ASP.NET 路由处理器。这个想法是,您向 ASP.NET 运行时注册这个路由处理程序,它提供了所有的管道,用于将 ASP.NET HTTP 处理程序将接收的调用和请求映射到您通过 PicoMvc 定义的处理程序函数。
因为`PicoMvcRouteHandler`只是一个普通的 HTTP 处理程序。它要求您在`global.asax`中向 ASP.NET 运行时注册它:
......@@ -91,7 +91,7 @@ PicoMvc 旨在将 F#函数映射到 URL 和 HTTP 动词。这个想法是,基
```
`PicoMvcRouteHandler`也需要一点配置。路由处理程序的第一个参数是一个字符串,它告诉它添加路由处理程序时匹配的 URL 的名称。然后,它将使用这个作为 URL 来解析将调用哪个函数。下一个参数是路由表,它保存着应该为哪些 URL 调用哪些函数的信息。您可以通过调用静态方法`LoadFromCurrentAssemblies`,使 PicoMvc 自动在所有加载的程序集中搜索标记有`[<Controller>]`属性的 F#模块。
`PicoMvcRouteHandler`也需要一点配置。路由处理程序的第一个参数是一个字符串,它告诉它添加路由处理程序时匹配的 URL 的名称。然后,它将使用这个作为 URL 来解析将调用哪个函数。下一个参数是路由表,它保存着应该为哪些 URL 调用哪些函数的信息。您可以通过调用静态方法`LoadFromCurrentAssemblies`,使 PicoMvc 自动在所有加载的程序集中搜索标记有`[<Controller>]`属性的 F# 模块。
```fs
let routingTables = RoutingTable.LoadFromCurrentAssemblies()
......@@ -163,7 +163,7 @@ PicoMvc 旨在将 F#函数映射到 URL 和 HTTP 动词。这个想法是,基
首先我们定义一个类型,`AutoCompleteResult`,来保存我们想要发送回客户端的结果。这将被直接翻译成 JSON。
接下来我们定义一个 PicoMvc 控制器。这只是一个标有`[<Controller>]`属性的 F#模块。因为模块的名字是`Commune`,所以它会暴露在 **~/commune.xxx** 的网址上,其中 xxx 用于确定哪个视图将用于渲染结果(我们如何选择视图来处理结果将在后面讨论)。在这种情况下,我们的网址将是 **~/commune.json** ,视图将把结果呈现为 json。
接下来我们定义一个 PicoMvc 控制器。这只是一个标有`[<Controller>]`属性的 F# 模块。因为模块的名字是`Commune`,所以它会暴露在 **~/commune.xxx** 的网址上,其中 xxx 用于确定哪个视图将用于渲染结果(我们如何选择视图来处理结果将在后面讨论)。在这种情况下,我们的网址将是 **~/commune.json** ,视图将把结果呈现为 json。
我们的控制器定义了处理它可能接收到的不同 HTTP 动词的函数。在这种情况下,我们只想处理 GET 动词请求,所以我们定义了一个`get`函数。该函数的参数项将由查询字符串中的项目`term`填充,`store`将由对 RavenDB 文档存储的引用填充。
......@@ -179,4 +179,4 @@ PicoMvc 旨在将 F#函数映射到 URL 和 HTTP 动词。这个想法是,基
## 总结
就这样。这需要一点解释,但是我们在这个过程中学习了很多关于 PicoMvc 的知识,最终的解决方案根本没有太多代码。事实上,整个解决方案大约有 150 行 F#和 C#。你可以在[的【github 上的 PicoMvc 的**示例**目录中看到最终的解决方案。](https://github.com/robertpi/PicoMvc/tree/master/examples/AutoComplete)
\ No newline at end of file
就这样。这需要一点解释,但是我们在这个过程中学习了很多关于 PicoMvc 的知识,最终的解决方案根本没有太多代码。事实上,整个解决方案大约有 150 行 F# 和 C#。你可以在[的【github 上的 PicoMvc 的**示例**目录中看到最终的解决方案。](https://github.com/robertpi/PicoMvc/tree/master/examples/AutoComplete)
\ No newline at end of file
# 进一步阅读
# 九、进一步阅读
希望你喜欢这篇关于 F#的介绍。如果它启发了你去学习更多关于 F#的知识,还有很多其他的材料可以用来进一步阅读。官方的 for F#开发中心有大量关于 F #的资料和许多指向 http://fsharp.net社区资源的跳转点。
希望你喜欢这篇关于 F# 的介绍。如果它启发了你去学习更多关于 F# 的知识,还有很多其他的材料可以用来进一步阅读。官方的 for F# 开发中心有大量关于 F #的资料和许多指向 http://fsharp.net社区资源的跳转点。
关于 F#的另一个很好的信息来源是包含 F#内容的开发者博客。各种各样的博主用不同的观点写 F#的文章。这里只是几个开始:
关于 F# 的另一个很好的信息来源是包含 F# 内容的开发者博客。各种各样的博主用不同的观点写 F# 的文章。这里只是几个开始:
* 唐·赛姆在 http://blogs.msdn.com/b/dsyme/的博客。F#项目的 F#创建者和首席架构师。
* F#团队博客:[http://blogs.msdn.com/b/fsharpteam/](http://blogs.msdn.com/b/fsharpteam/)
* 唐·赛姆在 http://blogs.msdn.com/b/dsyme/的博客。F# 项目的 F# 创建者和首席架构师。
* F# 团队博客:[http://blogs.msdn.com/b/fsharpteam/](http://blogs.msdn.com/b/fsharpteam/)
* 我自己的博客,虽然更新可能有点零星:[http://strangelights.com/blog](http://strangelights.com/blog)
F#社区有很多人活跃在推特上。定期关注推特的 *fsharp* 标签是了解最新 F#新闻的另一个好方法。
F# 社区有很多人活跃在推特上。定期关注推特的 *fsharp* 标签是了解最新 F# 新闻的另一个好方法。
如果你对更多关于 F#的书感兴趣,可以考虑:
如果你对更多关于 F# 的书感兴趣,可以考虑:
*始于 F#* 罗伯特·皮克林,阿珀斯,2009 年 12 月。我自己对 F#的介绍。它包括对语言语法的更完整和详细的解释,以及关于并行编程和面向语言编程等主题的章节。
*始于 F#* 罗伯特·皮克林,阿珀斯,2009 年 12 月。我自己对 F# 的介绍。它包括对语言语法的更完整和详细的解释,以及关于并行编程和面向语言编程等主题的章节。
*唐·赛姆等人的专家 F#* ,Apress,2010 年 6 月。这是一个优秀的 F#指南,由语言的创造者编写,毫不羞耻地针对专业程序员。
\ No newline at end of file
*唐·赛姆等人的专家 F#* ,Apress,2010 年 6 月。这是一个优秀的 F# 指南,由语言的创造者编写,毫不羞耻地针对专业程序员。
\ No newline at end of file
......@@ -2,4 +2,4 @@
在这个时代,地理信息系统无处不在,但大多数人,甚至开发人员,都不知道它的内部。我们中的许多人通过基于网络的系统使用地理信息系统,如谷歌地图或必应地图;作为推动地图和地址搜索的 GPS 数据;甚至在追踪你最新的亚马逊包裹时。
地理信息系统世界使用制图、统计分析和数据库技术的复杂组合来驱动驱动我们都使用和喜欢的所有流行外部应用程序的内部。在本指南中,我将向您展示这个世界的内部,以及它是如何应用的。NET 开发人员,他们可能对在最新的应用程序中使用一些地理信息系统功能感兴趣。
\ No newline at end of file
地理信息系统世界使用制图、统计分析和数据库技术的复杂组合来驱动驱动我们都使用和喜欢的所有流行外部应用的内部。在本指南中,我将向您展示这个世界的内部,以及它是如何应用的。NET 开发人员,他们可能对在最新的应用中使用一些地理信息系统功能感兴趣。
\ No newline at end of file
......@@ -2,9 +2,9 @@
对大多数人来说,他们所看到的地理信息系统实际上只是前端输出层,比如谷歌地图中生成的地图,或者汤姆汤姆导航设备上的屏幕。这一切的现实远不止于此;输出层通常是许多互连程序和大量数据的最终结果。
典型的地理信息系统将包括用于可视化、编辑和管理数据的桌面应用程序、存储数据的几种不同类型的后端数据库,以及在许多情况下大量定制的软件工具。事实上,地理信息系统是顶尖的行业之一,程序员可以编写大量其他公司没有的定制工具。
典型的地理信息系统将包括用于可视化、编辑和管理数据的桌面应用、存储数据的几种不同类型的后端数据库,以及在许多情况下大量定制的软件工具。事实上,地理信息系统是顶尖的行业之一,程序员可以编写大量其他公司没有的定制工具。
我们将很快详细探讨一些应用程序,但现在我们将继续 100 英尺的视图。典型的地理信息系统处理设置如下所示:
我们将很快详细探讨一些应用,但现在我们将继续 100 英尺的视图。典型的地理信息系统处理设置如下所示:
![](img/image001.png)
......@@ -48,7 +48,7 @@
由于大多数地理信息系统的中心都有一个大型数据库,所以 SQL 仍然扮演着重要的角色,而且可能永远都是。然而,从地理信息系统的角度来看,这些查询不仅涉及到您在数据库管理系统中习惯看到的普通 SQL,还涉及到地理空间 SQL。稍后我们将讨论特定于地理信息系统的 SQL 目前,这里的输入通常是从类似搜索查询的东西中生成的。
例如,当您在谷歌、必应或雅虎地图中键入地名或邮政编码时,您正在查看的网络应用程序很可能会将您的搜索转化为使用地理空间 SQL 来检查核心数据库中数据的查询。反过来,这将与其他过程结合产生一个输出,在这种情况下,它通常是一个显示您搜索的位置的地图。另一个例子可能是紧急服务控制室中的操作员进入事故地点,并将其与附近紧急车辆的已知地点相结合,以帮助决定将哪辆车辆送往事故地点。
例如,当您在谷歌、必应或雅虎地图中键入地名或邮政编码时,您正在查看的网络应用很可能会将您的搜索转化为使用地理空间 SQL 来检查核心数据库中数据的查询。反过来,这将与其他过程结合产生一个输出,在这种情况下,它通常是一个显示您搜索的位置的地图。另一个例子可能是紧急服务控制室中的操作员进入事故地点,并将其与附近紧急车辆的已知地点相结合,以帮助决定将哪辆车辆送往事故地点。
### 位置感知输入
......@@ -126,7 +126,7 @@ MySQL 也有类似的限制,但对许多核心数据类型的处理方式也
所有符合 OGC 标准的地理信息系统数据库必须支持两个核心元数据表,称为**几何 _ 列****空间 _ 参考 _ 系统**。大多数支持地理信息系统的软件将使用这些表的存在来确定它是否正在与真正的地理信息系统数据库系统对话。如果这些表不存在,软件通常会退出。
这方面的一个很好的例子是早期版本的 MySQL,其中表名由数据库引擎保留,但实际上并不作为表存在。这将导致 MapInfo 应用程序尝试创建缺失的表,但在尝试这样做时会收到一个错误,从而阻止软件正确使用数据库。
这方面的一个很好的例子是早期版本的 MySQL,其中表名由数据库引擎保留,但实际上并不作为表存在。这将导致 MapInfo 应用尝试创建缺失的表,但在尝试这样做时会收到一个错误,从而阻止软件正确使用数据库。
**geometry_columns** 表用于记录数据库中哪些表列包含地理空间数据以及它们的数据类型、坐标系、尺寸和一些其他相关信息。
......@@ -221,7 +221,7 @@ MySQL 也有类似的限制,但对许多核心数据类型的处理方式也
54.852726, -1.832299
如果你的手机内置了全球定位系统,启动它并观看显示屏。你会看到类似于这个坐标对的东西。请注意,在某些设备和应用程序上,坐标可能会互换。
如果你的手机内置了全球定位系统,启动它并观看显示屏。你会看到类似于这个坐标对的东西。请注意,在某些设备和应用上,坐标可能会互换。
这个坐标对被称为纬度和经度。第一个数字,纬度,是从赤道向北或向南的度数,北为正,南为负。第二个数字,经度,是本初子午线以东或以西的度数,西为负,东为正。该坐标系的正确地理空间名称为 **WGS84** 。在**空间参考系统**表中,其 SRID 号为 **4326**
......@@ -237,9 +237,9 @@ MySQL 也有类似的限制,但对许多核心数据类型的处理方式也
**srtext** 字段保存投影、椭球体、椭球体和其他基本信息,允许任何软件从一个坐标集转换到另一个坐标集。稍后我们将对此进行更多的介绍,但是对这一领域的所有内容的完整描述远远超出了这本小书的范围。事实上,我看过的描述基础知识的最小的一本书超过了 500 页!
**proj4text** 字段有类似的用途,但被使用开源 Proj.4 库的应用程序使用。
**proj4text** 字段有类似的用途,但被使用开源 Proj.4 库的应用使用。
Proj.4 和 Geos 是第一批由许多不同的空间数据库和地理信息系统应用程序使用的两个开源库。这两个库现在几乎 100%用于所有商业和开源软件,用于任何类型的空间或地理信息系统工作。这两个库仍在积极维护中,可用于您期望使用的每个平台。稍后,当我们简单了解一下可用于的一些地理信息系统软件时,我们将再次与他们见面。NET 开发人员。
Proj.4 和 Geos 是第一批由许多不同的空间数据库和地理信息系统应用使用的两个开源库。这两个库现在几乎 100%用于所有商业和开源软件,用于任何类型的空间或地理信息系统工作。这两个库仍在积极维护中,可用于您期望使用的每个平台。稍后,当我们简单了解一下可用于的一些地理信息系统软件时,我们将再次与他们见面。NET 开发人员。
目前,您需要注意的是,为了支持不同的空间坐标系,您必须在 **spatial_ref_sys** 表中有条目。
......@@ -261,7 +261,7 @@ SRID WGS84:4326-全球纬度/经度,带分钟/小时/秒偏移的度数,原
我想愉快地送你进入你的第一次地理信息系统冒险,并说这东西真的不重要;然而,事实是我不能,这很重要。事实上,这很重要。
如果你不能正确理解这个坐标,就有可能把一辆汽车的轨迹绘制成位于大西洋中部。虽然这对于您正在处理的应用程序可能无关紧要,例如,您可能正在查看客户分散的总体概述,但您仍然应该尽量确保您的应用程序尽可能准确。
如果你不能正确理解这个坐标,就有可能把一辆汽车的轨迹绘制成位于大西洋中部。虽然这对于您正在处理的应用可能无关紧要,例如,您可能正在查看客户分散的总体概述,但您仍然应该尽量确保您的应用尽可能准确。
所以这个价值百万的问题的答案是,“为什么我们要处理所有这些坐标的东西?”归结为一件事,也只有一件事:
......
......@@ -2,9 +2,9 @@
拥有一个设计良好的地理信息系统数据库很好,但是除此之外,你还需要什么软件呢?
除非您从头开始做所有事情,否则您将需要某种编辑应用程序、某种加载数据的方式,并且很可能还需要某种实时数据。
除非您从头开始做所有事情,否则您将需要某种编辑应用、某种加载数据的方式,并且很可能还需要某种实时数据。
主要问题是费用。你会很快发现,地理信息系统软件可能是地球上最昂贵的软件市场之一。物超所值,大多数这些应用程序的总体成本远远超过小型办公室典型的年度操作系统站点许可成本—通常一个应用程序中只有一个用户需要使用 6 个月。
主要问题是费用。你会很快发现,地理信息系统软件可能是地球上最昂贵的软件市场之一。物超所值,大多数这些应用的总体成本远远超过小型办公室典型的年度操作系统站点许可成本—通常一个应用中只有一个用户需要使用 6 个月。
对我们来说幸运的是,围绕地理信息系统也有一场巨大的开源和自由软件运动,大部分由开源地理空间基金会(OSGeo)运营和管理。
......@@ -66,7 +66,7 @@ SQL Server 官方网站是[www.microsoft.com/sqlserver/en/us/default.aspx](http:
### SQLite 和 SpatiaLite
SQLite 严格来说不是数据库服务器,而是新一代单文件数据库引擎之一,旨在直接嵌入到您的应用程序中。SQLite 在大量平台上都有惊人的支持,可能是我有幸使用过的最跨平台的工具包之一。
SQLite 严格来说不是数据库服务器,而是新一代单文件数据库引擎之一,旨在直接嵌入到您的应用中。SQLite 在大量平台上都有惊人的支持,可能是我有幸使用过的最跨平台的工具包之一。
与已经提到的三大巨头相比,SQLite 相对来说是一个新手,但它运行得非常好,效率非常高,尤其是在移动平台上。事实上,它在移动平台上表现如此出色,以至于被选为安卓设备和苹果 iOS 上的首选数据库引擎,并通过使用完全托管的。NET 接口。
......@@ -105,9 +105,9 @@ SQLite 网站是[sqlite.org](http://sqlite.org/)。它的。NET 接口可在[htt
## 地理信息系统桌面软件
为了操作您的地理信息系统资产,您需要一个好的桌面应用程序——最好是一个不仅允许您查看和操作数据,而且允许您相对容易地导入和导出数据的应用程序
为了操作您的地理信息系统资产,您需要一个好的桌面应用——最好是一个不仅允许您查看和操作数据,而且允许您相对容易地导入和导出数据的应用
后一点也很重要,因为有些应用程序的唯一目的是将数据移入和移出系统,而其他应用程序仅用于查看数据。移动数据的应用程序通常被称为 ETL(提取、转换和加载)包。ETL 包通常可用于许多数据库引擎,而不仅仅是那些用于操作地理空间数据的引擎。
后一点也很重要,因为有些应用的唯一目的是将数据移入和移出系统,而其他应用仅用于查看数据。移动数据的应用通常被称为 ETL(提取、转换和加载)包。ETL 包通常可用于许多数据库引擎,而不仅仅是那些用于操作地理空间数据的引擎。
幸运的是,大多数软件都允许你两者兼得。从这些包开始,下面是一些比较著名的包:
......@@ -147,9 +147,9 @@ SQLite 网站是[sqlite.org](http://sqlite.org/)。它的。NET 接口可在[htt
### 量子地理信息系统
我不能说量子地理信息系统(QGIS)公正。这个包可以做任何事情。它与 ESRI 和 MapInfo 等应用程序不相上下,完全开源,并得到了 OSGeo 基金会的官方支持。
我不能说量子地理信息系统(QGIS)公正。这个包可以做任何事情。它与 ESRI 和 MapInfo 等应用不相上下,完全开源,并得到了 OSGeo 基金会的官方支持。
主应用程序是使用 Python 编写的,因此将在 Linux、Mac OS、Windows 以及桌面环境中支持 Python 的任何其他设备上运行。
主应用是使用 Python 编写的,因此将在 Linux、Mac OS、Windows 以及桌面环境中支持 Python 的任何其他设备上运行。
现在在 1.8.0 版本上,量子地理信息系统的发展在它可用的相对短的时间内建立了强大的基础。系统公开的扩展 API 简直令人惊叹,可以在每个级别进行定制——从重新设计主 UI,到公开实时 GPS 跟踪等内容的插件,再到通过将算法应用到包中的不同层来创建全新的矢量层。
......@@ -171,13 +171,13 @@ SQLite 网站是[sqlite.org](http://sqlite.org/)。它的。NET 接口可在[htt
### MapWindow
MapWindow 的设计与 QGIS 非常相似。它的主要目的是做桌面地理信息系统应用程序可以做的一切,具有各种功能。
MapWindow 的设计与 QGIS 非常相似。它的主要目的是做桌面地理信息系统应用可以做的一切,具有各种功能。
这也是唯一一个专门为视窗平台编写的,旨在通过其丰富的开发人员应用编程接口和工具集涵盖视窗开发人员社区。
MapWindow 有两个版本:MapWindow 4 和 MapWindow 6。MapWindow 4 是最初的第一代 C++版本,MapWindow 6 是最新的、最先进的重写,完全使用 C#和标准编写。NET 运行时。
根据应用程序的 Codeplex 页面,目前这两个版本是同步更新和发布的。这是因为地图窗口 6 还没有达到与地图窗口 4 相同的功能级别。正如您在下面的截图中看到的,它与 QGIS 非常相似:
根据应用的 Codeplex 页面,目前这两个版本是同步更新和发布的。这是因为地图窗口 6 还没有达到与地图窗口 4 相同的功能级别。正如您在下面的截图中看到的,它与 QGIS 非常相似:
![](img/image008.jpg)
......@@ -187,11 +187,11 @@ MapWindow 有两个版本:MapWindow 4 和 MapWindow 6。MapWindow 4 是最初的
### 地理水壶
另一个值得一提的应用是 GeoKettle。虽然这不是一个桌面地理信息系统应用程序,但它同样重要。
另一个值得一提的应用是 GeoKettle。虽然这不是一个桌面地理信息系统应用,但它同样重要。
GeoKettle 是一个 ETL 工具。它的主要目的是在多种格式和多种类型的数据库之间转换和加载数据。源自一个名为 Pentaho 数据套件的包,GeoKettle 得到了增强,以支持行业标准的 shapefiles、KML 文件以及前面提到的所有数据库的空间特征。
一个简单易用的开源应用程序可以做得多好的鲜明例子是,我看到许多人用基于 GeoKettle 的解决方案取代了高价应用程序,如安全 FME。
一个简单易用的开源应用可以做得多好的鲜明例子是,我看到许多人用基于 GeoKettle 的解决方案取代了高价应用,如安全 FME。
用 Java 编写,它有一个非常容易扩展的插件架构,使得它很容易处理未来的文件格式和数据库。它还可以处理数据库和文件中的正常数据,而不仅仅是地理空间数据。如果您曾经使用过微软商业智能开发工作室,那么使用 GeoKettle 就像在家里一样,您会在下面的截图中注意到这一点:
......@@ -207,15 +207,15 @@ GeoKettle 是一个 ETL 工具。它的主要目的是在多种格式和多种
我个人最喜欢的两个是 QGIS 和 GeoKettle,但是我鼓励你尽你所能去尝试。这些年,我用了很多桌面 GIS 包;有些学习曲线非常陡峭,有些你不到五分钟就能学会。和任何事情一样,你应该选择一个工具,尽可能以最好和最简单的方式完成你需要完成的工作。
请注意,我列出的应用程序主要在英国和欧洲使用。应用程序的受欢迎程度在世界各地各不相同。例如,我认为 IDRISI 是加拿大流行的软件包。本节列出的应用程序是我在日常地理信息系统工作中使用的应用程序
请注意,我列出的应用主要在英国和欧洲使用。应用的受欢迎程度在世界各地各不相同。例如,我认为 IDRISI 是加拿大流行的软件包。本节列出的应用是我在日常地理信息系统工作中使用的应用
正如我已经提到的,除了你选择的软件,你还有很多其他的事情要处理。
## 开发套件
因为这本书是针对。NET 开发人员,这是唯一的权利,我们包括一个部分的套件可用的地理空间数据在您自己的。NET 应用程序
因为这本书是针对。NET 开发人员,这是唯一的权利,我们包括一个部分的套件可用的地理空间数据在您自己的。NET 应用。
稍后我们将介绍一些实际的例子,但现在我将列出我使用过或看到过的工具包。然而,请注意,这不是一个详尽的清单。我描述的工具包都是为在下使用而设计的。NET 在 Windows 平台上实现。正如我所提到的,像 QGIS 这样的应用程序可以被极大地扩展,在 Linux 和 Mac 系统下有许多工具包是我还没有也可能不会涉及的。如果你正在开始一个项目,你知道你将要写定制的用户界面,提前做你的研究。您可以修改现有的应用程序来满足您的需求,而不是从头开始编写它们。
稍后我们将介绍一些实际的例子,但现在我将列出我使用过或看到过的工具包。然而,请注意,这不是一个详尽的清单。我描述的工具包都是为在下使用而设计的。NET 在 Windows 平台上实现。正如我所提到的,像 QGIS 这样的应用可以被极大地扩展,在 Linux 和 Mac 系统下有许多工具包是我还没有也可能不会涉及的。如果你正在开始一个项目,你知道你将要写定制的用户界面,提前做你的研究。您可以修改现有的应用来满足您的需求,而不是从头开始编写它们。
### 地图赢取
......@@ -223,7 +223,7 @@ MapWinGis 是 MapWindow 4 和 MapWindow 6 背后的中央 GUI 组件。这是一
过去,我使用这个组件的原始版本。我已经有一段时间没有使用它进行任何开发了。与许多这些组件一样,它在 mapwingis.codeplex.com 的 Codeplex 上有一个永久的家。
它旨在为您完成大部分繁重的工作,让您可以自由地专注于应用程序的图形用户界面方面。请注意,它是为桌面应用程序设计的,而不是基于网络的应用程序,据我所知,不能在 WPF 或 Silverlight 中使用。
它旨在为您完成大部分繁重的工作,让您可以自由地专注于应用的图形用户界面方面。请注意,它是为桌面应用设计的,而不是基于网络的应用,据我所知,不能在 WPF 或 Silverlight 中使用。
### 点空间
......@@ -267,7 +267,7 @@ BruTile 可以用于任何类型的项目,从 web 和 Silverlight,到高端
对于编程示例,我将在 Visual Studio 2010 Professional 中使用 C#语言的夏普映射。样品可从[bitbucket.org/syncfusion/gis-succinctly](https://bitbucket.org/syncfusion/gis-succinctly)下载。
请注意,我不会介绍如何安装和初始设置这些应用程序。在大多数情况下,这是一个相当简单的操作,我假设这本书的读者都很熟悉。如果您对安装软件有任何问题,本书中提到的所有应用程序都有非常活跃的社区和帮助论坛。
请注意,我不会介绍如何安装和初始设置这些应用。在大多数情况下,这是一个相当简单的操作,我假设这本书的读者都很熟悉。如果您对安装软件有任何问题,本书中提到的所有应用都有非常活跃的社区和帮助论坛。
对于熟悉堆栈溢出的人来说,可以在[gis.stackexchange.com](http://gis.stackexchange.com/)找到它的地理信息系统专用站点。
......
......@@ -10,11 +10,11 @@
在我们开始向系统中添加任何数据之前,我们首先需要创建一个数据库来存储数据。对于本书中的示例,我将创建一个简单的三表数据库,而不是前面描述的整个地理信息系统模型。
如果您正在处理一个大型企业应用程序,我再怎么强调规划和设计在地理信息系统数据库解决方案中的重要性也不为过。在许多方面,这方面的计划比普通数据库中的相同步骤要重要得多。与一般的企业数据解决方案相比,地理信息系统解决方案的故障和变更往往更昂贵、更复杂。
如果您正在处理一个大型企业应用,我再怎么强调规划和设计在地理信息系统数据库解决方案中的重要性也不为过。在许多方面,这方面的计划比普通数据库中的相同步骤要重要得多。与一般的企业数据解决方案相比,地理信息系统解决方案的故障和变更往往更昂贵、更复杂。
为了创建数据库,我们将使用 Postgres 提供的数据库管理工具 pgAdmin。要启动 pgAdmin,点击桌面上的 **pgAdmin III** 图标。如果看不到图标,请确保在安装服务器时安装了管理工具。
安装应用程序并创建与数据库服务器的初始连接后,您可以开始在该服务器连接中创建数据库,如下图所示。
安装应用并创建与数据库服务器的初始连接后,您可以开始在该服务器连接中创建数据库,如下图所示。
请注意,出于安全原因,我已经从本书中显示 pgAdmin 的许多图中删除了服务器和表名,只留下了那些您理解所必需的名称。在您使用 pgAdmin 的过程中,当您完成我在这里介绍的步骤时,您会看到更多的信息。
......@@ -64,7 +64,7 @@ Postgres **Contrib** 目录(位于您选择安装 Postgres 的位置)中有脚
如果您使用 Postgres 帐户创建所有表,您不会有问题,但是如果您创建数据库,然后将这些数据库的所有权分配给您在服务器中创建的其他用户名,您可能会发现 **Postgres** 用户帐户无法使用它们。
在 QGIS 中打开数据库图层时,最有可能出现这个问题。如果使用给定的一组凭据创建数据库连接,并使用 **Postgres** 用户帐户在 pgAdmin 中创建数据库,您会发现空间元数据表将有 **Postgres** 作为其所有者。发生这种情况时,QGIS 将无法打开元数据表,并且不会显示可供您在应用程序中使用的图层。
在 QGIS 中打开数据库图层时,最有可能出现这个问题。如果使用给定的一组凭据创建数据库连接,并使用 **Postgres** 用户帐户在 pgAdmin 中创建数据库,您会发现空间元数据表将有 **Postgres** 作为其所有者。发生这种情况时,QGIS 将无法打开元数据表,并且不会显示可供您在应用中使用的图层。
这个问题的解决方法很简单。使用 pgAdmin,右键单击其中一个元数据表,选择**属性**选项,如下图所示:
......@@ -78,7 +78,7 @@ Postgres **Contrib** 目录(位于您选择安装 Postgres 的位置)中有脚
图 17:编辑几何列表属性
**所有者**字段提供了服务器中定义的用户的下拉列表。选择您在应用程序连接中使用的所有者。
**所有者**字段提供了服务器中定义的用户的下拉列表。选择您在应用连接中使用的所有者。
### 重访元数据表
......@@ -116,7 +116,7 @@ Postgres **Contrib** 目录(位于您选择安装 Postgres 的位置)中有脚
这个接口是相当不言自明的。您可以在 **PostgreSQL** **连接**区域找到与您列出的 SQL 数据库的任何连接。**导入选项**用于指定数据的 SRID 等内容,以及数据导入的其他选项。
您的 PostgreSQL 连接列表在此处和主应用程序之间共享。如果您已经在 QGIS 中创建了一个连接,您只需从下拉列表中选择它并单击**连接**,就可以在这里重用它。
您的 PostgreSQL 连接列表在此处和主应用之间共享。如果您已经在 QGIS 中创建了一个连接,您只需从下拉列表中选择它并单击**连接**,就可以在这里重用它。
然而,在本练习中,我们将创建一个新的连接来保存我们的数据。首先,点击**邮箱连接**下的**新建**。将出现**创建新的邮政地理信息系统连接**对话框。
......
......@@ -8,13 +8,13 @@
在下一节中,我不打算涵盖所有可能的排列和函数调用。根据最新统计,OGC 规范中有 300 多个独立函数,涵盖了从空间距离关系到复杂几何结构的构建,再到为预定义矢量路径裁剪栅格的几乎所有可能情况。
相反,使用我们放在数据库中的数据,我将指导您完成一些简单但常见的操作——任何编写支持地理信息系统的应用程序的人都可能使用的类型。
相反,使用我们放在数据库中的数据,我将指导您完成一些简单但常见的操作——任何编写支持地理信息系统的应用的人都可能使用的类型。
在讨论这些操作之前,让我们先快速了解一下第一章中描述的输入和输出阶段。
## 创建和检索几何图形
即使我们已经将一些数据导入到我们的数据库中,任何编写地理信息系统应用程序的人也需要能够在数据库中创建几何图形,尤其是如果应用程序允许编辑的话。
即使我们已经将一些数据导入到我们的数据库中,任何编写地理信息系统应用的人也需要能够在数据库中创建几何图形,尤其是如果应用允许编辑的话。
大多数几何图形创建是以三种格式之一执行的:
......@@ -152,7 +152,7 @@ Postgres 最新版本中提供的其他几何功能包括:
这将返回一个可直接插入输出或 SVG 文件的 SVG 标记。
如果您正在创建用于谷歌地球或任何其他支持锁眼标记语言的应用程序的输出,请使用以下功能:
如果您正在创建用于谷歌地球或任何其他支持锁眼标记语言的应用的输出,请使用以下功能:
```sql
SELECT ST_AsKML(geometry)
......@@ -182,7 +182,7 @@ Postgres 最新版本中提供的其他几何功能包括:
```
这将输出 NMEA 秒、分和度格式的坐标,但这种格式的使用被认为是非标准的,可能会使您的应用程序很难在数据库平台之间移植。
这将输出 NMEA 秒、分和度格式的坐标,但这种格式的使用被认为是非标准的,可能会使您的应用很难在数据库平台之间移植。
让我们使用添加到数据库中的城市点数据来快速查看其中的一两个函数。为此,我们将使用 pgAdmin 中的 SQL 编辑器。要打开 SQL 编辑器,请选择您希望使用的数据库,在我们的例子中是**注册表**如果您一直在关注的话,请选择它,然后单击工具栏上的 SQL 放大镜图标。
......
# 第 5 章在中创建地理信息系统应用程序。网
# 第 5 章在中创建地理信息系统应用。网
所以最后我们来到了你们大多数人一直在等待的部分:在. NET 中创建一个支持 GIS 的小型桌面应用程序
所以最后我们来到了你们大多数人一直在等待的部分:在. NET 中创建一个支持 GIS 的小型桌面应用
在这一章中,我使用 Visual Studio 2010 Ultimate 进行任何截图,我的代码是用 C#编写的。
......@@ -26,11 +26,11 @@
## 创建我们自己的夏普地图解决方案
运行 Visual Studio 的一个实例或重用您仍然打开的实例,并创建一个新的 Windows 窗体应用程序
运行 Visual Studio 的一个实例或重用您仍然打开的实例,并创建一个新的 Windows 窗体应用。
![](img/image069.jpg)
图 69:启动新的 Windows 窗体应用程序
图 69:启动新的 Windows 窗体应用
确保你正在使用。NET 4。SharpMap 的当前版本针对的是。NET 4 及以上版本。
......@@ -39,7 +39,7 @@
| ![](img/image070.png) | | ![](img/image071.png) |
| 图 70:改变目标框架 |
现在我们需要将夏普地图用户界面组件添加到我们的工具箱中。双击**解决方案资源管理器**中的**表单 1.cs** 加载工具栏选项板。在**通用**下方的空白区域点击右键,选择**添加标签**。给标签起一个名字。在我的应用程序中,我调用了选项卡夏普地图。
现在我们需要将夏普地图用户界面组件添加到我们的工具箱中。双击**解决方案资源管理器**中的**表单 1.cs** 加载工具栏选项板。在**通用**下方的空白区域点击右键,选择**添加标签**。给标签起一个名字。在我的应用中,我调用了选项卡夏普地图。
创建调色板后,将其展开并右键单击**调色板**区域。从出现的菜单中选择**选择项目**。将出现**选择工具箱项目**对话框。
......@@ -116,7 +116,7 @@
图 76:pgAdmin 中的对象树
如图所示,**表格**节点下是一个名为**视图**的绿色小图标。您可能以前在其他数据库中使用过这些。总的想法是,它们将其他表中的数据投影到不同的模式中,但在客户端应用程序看来,它们就像一个实际的表。
如图所示,**表格**节点下是一个名为**视图**的绿色小图标。您可能以前在其他数据库中使用过这些。总的想法是,它们将其他表中的数据投影到不同的模式中,但在客户端应用看来,它们就像一个实际的表。
一个典型的用法是从通过外键链接的不同表中获取行,并呈现组合数据的简单平面视图,其中所有呈现的项形成一行而不是层次结构。
......@@ -184,7 +184,7 @@
图 80:带有新视图的表格
像任何符合 OGC 标准的地理信息系统数据库客户端的像样的实现一样,夏普地图将检查**几何 _ 列**表,找出我们添加的任何图层的细节。如果我们添加一个在 geometry_columns 表中找不到的视图,它将取消并产生一个异常。一旦我们手动添加了数据,我们就可以将这些视图加载到我们的应用程序中。
像任何符合 OGC 标准的地理信息系统数据库客户端的像样的实现一样,夏普地图将检查**几何 _ 列**表,找出我们添加的任何图层的细节。如果我们添加一个在 geometry_columns 表中找不到的视图,它将取消并产生一个异常。一旦我们手动添加了数据,我们就可以将这些视图加载到我们的应用中。
### 回到代码...
......@@ -320,7 +320,7 @@
最后,在对`InitializeComponent()`的调用下面添加对表单构造函数`InitializeMap()`的调用,这就是初始化函数所需的全部内容。
如果此时运行您的应用程序,并且所有设置都正确,您应该会看到您的地图图层出现在屏幕上。您应该能够通过在地图表面拖动指针来平移它们,并使用鼠标滚轮进行缩放。
如果此时运行您的应用,并且所有设置都正确,您应该会看到您的地图图层出现在屏幕上。您应该能够通过在地图表面拖动指针来平移它们,并使用鼠标滚轮进行缩放。
应该是这样的:
......@@ -360,7 +360,7 @@
SharpMap 有许多不同的工具模式,从缩放和平移到在加载的地图顶部绘制线条和多边形。
我们将在这个应用程序中使用的两个工具是默认的缩放和平移工具,以及查询工具。
我们将在这个应用中使用的两个工具是默认的缩放和平移工具,以及查询工具。
更改工具就像给表单上的`MapBox`控件的`ActiveTool`属性赋予一个新值一样简单。要分配的值是来自`MapBox.Tools`类型枚举的任何值。
......@@ -379,7 +379,7 @@ SharpMap 有许多不同的工具模式,从缩放和平移到在加载的地
```
如果您现在运行该应用程序,您应该能够使用表单左上角的两个按钮来更改模式。缩放和平移是自动处理的。对于查询,我们必须响应地图框上的点击事件,并添加一些代码来获得我们需要的结果。
如果您现在运行该应用,您应该能够使用表单左上角的两个按钮来更改模式。缩放和平移是自动处理的。对于查询,我们必须响应地图框上的点击事件,并添加一些代码来获得我们需要的结果。
### 添加我县信息查询码
......@@ -523,7 +523,7 @@ SharpMap 有许多不同的工具模式,从缩放和平移到在加载的地
```
在我们继续之前,你们中的一些人会说,“哇,多长的方法啊”,并想知道为什么我要使用`Application.DoEvents`来确保标签在事件处理程序中得到更新。请记住,这只是示例代码;它不应该是一个完美的例子,或者简单地复制并逐字粘贴来制作生产质量的应用程序。它的目的纯粹是向您展示如何使用夏普地图创建一个简单的地理信息系统应用程序
在我们继续之前,你们中的一些人会说,“哇,多长的方法啊”,并想知道为什么我要使用`Application.DoEvents`来确保标签在事件处理程序中得到更新。请记住,这只是示例代码;它不应该是一个完美的例子,或者简单地复制并逐字粘贴来制作生产质量的应用。它的目的纯粹是向您展示如何使用夏普地图创建一个简单的地理信息系统应用
### 结论
......@@ -608,7 +608,7 @@ SharpMap 完全能够获取我们之前找到的多边形轮廓,并查询地
我们在嵌套的`using`语句中完成了所有这些,这意味着一切都是`IDisposable`,一旦完成,就应该被正确释放,只需将结果的字符串列表返回给调用方法。
如果一切按计划进行,在点击**运行**时,您应该会看到一个应用程序,该应用程序可以缩放和平移数据库中定义的地图,还可以切换到`County Query Mode`并检索选定县的城镇列表。您完成的应用程序应该如下所示:
如果一切按计划进行,在点击**运行**时,您应该会看到一个应用,该应用可以缩放和平移数据库中定义的地图,还可以切换到`County Query Mode`并检索选定县的城镇列表。您完成的应用应该如下所示:
![](img/image085.jpg)
......@@ -616,4 +616,4 @@ SharpMap 完全能够获取我们之前找到的多边形轮廓,并查询地
我们找到了。希望我已经激起了你的食欲,并向你展示了地理信息系统在日常生活中可以帮助你的许多事情中的一些。
请记住,有可能买到足够大功率的手机来小规模地做这种事情,并且有数据库系统来支持它们,比如 SQL Compact。夏普地图允许你做任何事情,从矢量到光栅地图和更远。一旦你开始进一步观察,你会发现一些系统具有读取全球定位系统设备的内置能力,使你能够将实时位置信息拉入你的应用程序。走出去,探索现实世界和数字世界。这是一次刚刚开始的冒险。
\ No newline at end of file
请记住,有可能买到足够大功率的手机来小规模地做这种事情,并且有数据库系统来支持它们,比如 SQL Compact。夏普地图允许你做任何事情,从矢量到光栅地图和更远。一旦你开始进一步观察,你会发现一些系统具有读取全球定位系统设备的内置能力,使你能够将实时位置信息拉入你的应用。走出去,探索现实世界和数字世界。这是一次刚刚开始的冒险。
\ No newline at end of file
......@@ -2,7 +2,7 @@
| ![](img/00007.jpeg) | 提示:如果你有兴趣了解更多关于 Git 的知识,一定要下载 Ryan Hodson 的电子书《Git 简洁》。 |
在本地计算机上安装 Git 的第一步是访问 [GitHub Desktop](https://desktop.github.com/ "蘞뉘뿰ṝĽ纀篓") 网站并下载桌面应用程序
在本地计算机上安装 Git 的第一步是访问 [GitHub Desktop](https://desktop.github.com/ "蘞뉘뿰ṝĽ纀篓") 网站并下载桌面应用。
![](img/00010.jpeg)
......
......@@ -32,7 +32,7 @@
您可以看到存储库名称旁边的星星数量,如图 20 所示。如您所见,blueimp 的文件上传 jQuery 模块有超过 22,000 颗星。这可能是一个安全的赌注,它已经被大量开发人员测试和使用。
你也可以按照最少的星星来排序,但是你不应该认为星星少的项目是一个必要的坏项目。事实上,它拥有较少的恒星也可能证明这是一个未知的项目或新的贡献。这可能是一个伟大的项目,但很少有人需要它或已经发现它。在这些类型的项目中可能有一些隐藏的宝石,特别是如果你正在处理一个不常见的应用程序
你也可以按照最少的星星来排序,但是你不应该认为星星少的项目是一个必要的坏项目。事实上,它拥有较少的恒星也可能证明这是一个未知的项目或新的贡献。这可能是一个伟大的项目,但很少有人需要它或已经发现它。在这些类型的项目中可能有一些隐藏的宝石,特别是如果你正在处理一个不常见的应用。
虽然我们将在后面的章节中讨论 GitHub 分叉,但这里的简单描述应该会有所帮助。fork 是某人下载的存储库的副本,很可能是为了建议变更或者作为他们自己项目的起点。
......@@ -48,11 +48,11 @@
最近更新最少的首先显示最早的(就活动而言)。同样,项目更新日期仅提供项目活跃程度的概念。Scriptaculous(一个 JavaScript 框架)已经六个月没有更新了,但是已经有将近 2400 颗星了。这表明一个框架仍在使用,并且相当成熟。它实际上是在 2005 年写的(在互联网时代是古老的),在 2010 年被功能冻结,然而仍然在使用,并且仍然有贡献者被列在项目上,即使它被冻结了。
随着新浏览器和新技术的频繁出现,旧的网络项目可能无法与新技术兼容。请记住,E. 9 直到 2011 年才发布,所以这个特殊的框架(Scriptaculous)在 E. 8 版本中运行良好。这可能是一个很好的网络应用程序框架,其中的计算机较旧,并且没有运行最新的浏览器。
随着新浏览器和新技术的频繁出现,旧的网络项目可能无法与新技术兼容。请记住,E. 9 直到 2011 年才发布,所以这个特殊的框架(Scriptaculous)在 E. 8 版本中运行良好。这可能是一个很好的网络应用框架,其中的计算机较旧,并且没有运行最新的浏览器。
在排序选项、星星(使用项目后有多少开发人员喜欢它)、分叉(有多少开发人员对增强项目足够感兴趣)和活动(项目最近是如何工作的)之间,您应该能够为您的应用程序选择一个好的项目。
在排序选项、星星(使用项目后有多少开发人员喜欢它)、分叉(有多少开发人员对增强项目足够感兴趣)和活动(项目最近是如何工作的)之间,您应该能够为您的应用选择一个好的项目。
除了对结果进行排序,GitHub 搜索结果还提供了一些基本的过滤选项,主要是让您专注于特定的编程语言。例如,假设我们正在进行一个项目,将 QuickBooks 与您正在开发的某个应用程序集成在一起。在 GitHub 中搜索“QuickBooks”会得到 300 多个结果。如果我按照大多数星星对它们进行排序,我发现 PHP 和 Ruby 实现占据了前 10 名的结果。
除了对结果进行排序,GitHub 搜索结果还提供了一些基本的过滤选项,主要是让您专注于特定的编程语言。例如,假设我们正在进行一个项目,将 QuickBooks 与您正在开发的某个应用集成在一起。在 GitHub 中搜索“QuickBooks”会得到 300 多个结果。如果我按照大多数星星对它们进行排序,我发现 PHP 和 Ruby 实现占据了前 10 名的结果。
然而,在搜索结果的左侧,GitHub 显示了所有找到的存储库的语言组的分类。
......@@ -64,4 +64,4 @@
| ![](img/00003.gif) | 注意:请记住,用 C#编写的库可以从任何。NET 语言,如 Visual Basic。 |
GitHub 中的基本搜索以及排序和过滤选项应该允许您在存储库中移动并找到库、应用程序等。你需要开始你的发展努力。
\ No newline at end of file
GitHub 中的基本搜索以及排序和过滤选项应该允许您在存储库中移动并找到库、应用等。你需要开始你的发展努力。
\ No newline at end of file
......@@ -24,7 +24,7 @@ GitHub 的搜索引擎隐藏了搜索中的高级选项,但在搜索字符串
时区语言:javascript 星号:> 500
通过组合选项,您可以将返回的结果缩小到仅满足应用程序需求的解决方案。
通过组合选项,您可以将返回的结果缩小到仅满足应用需求的解决方案。
| ![](img/00007.jpeg) | 提示:虽然您可以创建一些相当大的搜索请求(例如所有超过 500 颗星的项目),但是除了高级搜索选项之外,您通常应该至少包含一个搜索词。 |
......
......@@ -232,6 +232,6 @@ Pulse 选项卡让您了解存储库的活跃程度;这个例子代表了 Boot
至少,我会提供一个简短(一段)的代码摘要,以及如何安装它(最低要求)。这至少可以刺激用户的食欲。然后,您可以提供更多的详细信息(在自述文件的剩余部分),或者在您的存储库中作为一个单独的文档文件。
本章详细介绍了 GitHub 提供的关于存储库的信息。您应该知道如何使用这些信息来帮助决定特定的存储库是否可以帮助您的应用程序,以及您是否可以为代码库做出贡献。
本章详细介绍了 GitHub 提供的关于存储库的信息。您应该知道如何使用这些信息来帮助决定特定的存储库是否可以帮助您的应用,以及您是否可以为代码库做出贡献。
在下一章中,我们将讨论如何获取代码供您个人使用或参与项目。
\ No newline at end of file
......@@ -28,7 +28,7 @@ NPM–v
如果您只是使用文本编辑器和终端窗口,就像本书的前几章一样,您可以按照以下步骤操作:
1. 创建一个用于制作应用程序的文件夹
1. 创建一个用于制作应用的文件夹
2. 打开该文件夹并键入 npm init。这将在您完成所有设置步骤后创建一个 **package.json** 文件。在设置过程中,您可以填写每一行,也可以通过按下**进入**键回答每一个问题并在最后回答**是**来快速浏览。
3. You can now install Gulp and Gulp plugins via the command:
......
......@@ -2,7 +2,7 @@
前一章完全是关于狼吞虎咽的谋生之道:任务。本章将讲述当文件或文件夹改变时的反应,然后相应地采取行动。这给了她相当大的力量,并使某些场景对开发人员来说更容易,这样她就可以更专注于工作,而不会被重复的步骤分散注意力。
在开发您的网站或 web 应用程序时,您知道在浏览器中看到您的更改之前,您必须进行一些手动操作。即使大口已经让任务变得更容易,它仍然需要一些手动干预,比如打开一些外壳,键入一个命令,比如大口生成宏文件。
在开发您的网站或 web 应用时,您知道在浏览器中看到您的更改之前,您必须进行一些手动操作。即使大口已经让任务变得更容易,它仍然需要一些手动干预,比如打开一些外壳,键入一个命令,比如大口生成宏文件。
如果我们能跳过这一部分,让大口自己解决问题,那不是很好吗?欢迎来到大口看 API。
......
这一章的目的是让读者进一步了解大口。我们将通过展示开发人员可能需要的小代码片段和日常任务的用法来做到这一点。
在过去的几年里,网络上 JavaScript 的使用有了惊人的增长。最初,它只是用来响应某个点击事件,以切换某个 HTML 元素(如图片)的可见性。如今,看到 web 应用程序使用数千行 JavaScript 代码,在浏览器中执行一堆任务,而不是将所有内容都回发到服务器并等待答案,这种情况也不例外。所谓的单页应用程序已经越来越受欢迎。但是它也有一个缺点:复杂性会变得非常棘手,而且很容易犯小错误。因此,我们也看到越来越多的工具和语言将你用它们写的代码转换成 JavaScript。通常,这是一项手动任务,过一段时间后可能会变得乏味。幸运的是,我们正在使用 glaugh . js,它通过自动化让生活变得更容易。
在过去的几年里,网络上 JavaScript 的使用有了惊人的增长。最初,它只是用来响应某个点击事件,以切换某个 HTML 元素(如图片)的可见性。如今,看到 web 应用使用数千行 JavaScript 代码,在浏览器中执行一堆任务,而不是将所有内容都回发到服务器并等待答案,这种情况也不例外。所谓的单页应用已经越来越受欢迎。但是它也有一个缺点:复杂性会变得非常棘手,而且很容易犯小错误。因此,我们也看到越来越多的工具和语言将你用它们写的代码转换成 JavaScript。通常,这是一项手动任务,过一段时间后可能会变得乏味。幸运的是,我们正在使用 glaugh . js,它通过自动化让生活变得更容易。
| ![](img/00021.gif) | 注意:Transpiling 是一个特定的术语,用来表示在保持相同抽象级别的同时将一种语言转换成另一种语言的过程——基本上是从 CoffeeScript、TypeScript…到 JavaScript。编译是从一种语言转换成另一种语言,就像将 C#编译成二进制代码(在这种情况下是 IL)。 |
......@@ -180,7 +180,7 @@ CoffeeScript 可能是我遇到的第一种在翻译后生成 JavaScript 的语
### 打字稿
TypeScript 是微软开发的语言,就像 CoffeeScript 一样,编译成 JavaScript。自从谷歌的 Angular.js 团队宣布密切合作以来,它现在获得了很多兴趣和动力。TypeScript 被选为编写即将到来的基于 Angular.js 的应用程序的首选语言。正如你已经感觉到的,这将是未来几年的大事。
TypeScript 是微软开发的语言,就像 CoffeeScript 一样,编译成 JavaScript。自从谷歌的 Angular.js 团队宣布密切合作以来,它现在获得了很多兴趣和动力。TypeScript 被选为编写即将到来的基于 Angular.js 的应用的首选语言。正如你已经感觉到的,这将是未来几年的大事。
如果你想了解更多关于 TypeScript 的知识,我建议你看看[这个网站](http://www.typescriptlang.org/),尤其是操场版块在工作的时候看看。这里使用的例子就是其中之一。
......@@ -711,7 +711,7 @@ Safari:
请注意,源映射不仅适用于 CSS,还可以用于从另一个源文件编译或传输的 JavaScript 文件。浏览器可以利用这一点来显示一些代码最初来自哪里。我们已经在[类型脚本](#_TypeScript_1)部分看到了一个 JavaScript 源图的例子。
载入特定任务要处理的文件,这是一个很好的工具。这些文件的加载顺序与文件夹中的顺序相同。这意味着如果你有文件需要在结果文件中以特定的顺序输出,你将不得不做一些操作。可能出现这种情况的情况是一堆 CSS 文件的串联。在这样的文件中,顺序非常重要,因为它可能会使您的应用程序看起来与您想要的不同。
载入特定任务要处理的文件,这是一个很好的工具。这些文件的加载顺序与文件夹中的顺序相同。这意味着如果你有文件需要在结果文件中以特定的顺序输出,你将不得不做一些操作。可能出现这种情况的情况是一堆 CSS 文件的串联。在这样的文件中,顺序非常重要,因为它可能会使您的应用看起来与您想要的不同。
拿下面三个小的来说。css 文件和大口文件:
......@@ -939,7 +939,7 @@ glow . js 是一个任务运行器,这意味着它在闭门造车的情况下
图 29:带有额外选项集的吞咽记录器模块的输出
great 非常擅长生成输出,并覆盖之前的输出。当在应用程序中设置一个*大口架构*时,你可能会在每一步都测试它。这最终可能会给出输出文件,而你可能不再需要这些文件,或者这些文件只是成为了一堆垃圾。潜在地,您可能会将剩余部分集成到您的实际解决方案中,降低性能,或者更糟,导致 bug。
great 非常擅长生成输出,并覆盖之前的输出。当在应用中设置一个*大口架构*时,你可能会在每一步都测试它。这最终可能会给出输出文件,而你可能不再需要这些文件,或者这些文件只是成为了一堆垃圾。潜在地,您可能会将剩余部分集成到您的实际解决方案中,降低性能,或者更糟,导致 bug。
因此,在执行“吞咽魔法”之前,最好从头开始,清除输出文件夹及其子文件夹。通常这是作为默认任务的从属任务来完成的,例如:
......
......@@ -220,13 +220,13 @@ Grunt 讲的都是配置而不是编码,而 glaugh 讲的都是通过代码进
图 33: Visual Studio 2015 开始屏幕
从接下来出现的模态窗口中(图 34),选择**ASP.NET 网络应用程序**。给它一个有意义的名称,并在您的机器上选择一个路径。确保选择了选项**为解决方案**创建目录。
从接下来出现的模态窗口中(图 34),选择**ASP.NET 网络应用**。给它一个有意义的名称,并在您的机器上选择一个路径。确保选择了选项**为解决方案**创建目录。
![](img/00038.jpeg)
图 34:选择 ASP.NET 网络应用程序
图 34:选择 ASP.NET 网络应用
点击**确定**按钮后,你会看到一个如图 35 所示的窗口。从 ASP.NET 5 预览模板中选择第三个选项,**网络应用程序**。点击**确定**
点击**确定**按钮后,你会看到一个如图 35 所示的窗口。从 ASP.NET 5 预览模板中选择第三个选项,**网络应用**。点击**确定**
![](img/00039.jpeg)
......@@ -240,9 +240,9 @@ Visual Studio 2015 现在将基于所选模板创建一个新的解决方案。
在项目的根**gulf invs**中,可以看到文件 gulpfile.js 也被添加到解决方案中。为了您的方便,它已经设置了一些初始代码。我们接下来会看到。
创建新的 ASP.NET 5 web 应用程序后,解决方案中已经有一个包含以下内容的 gulpfile.js:
创建新的 ASP.NET 5 web 应用后,解决方案中已经有一个包含以下内容的 gulpfile.js:
代码清单 60:新创建的 ASP.NET 5 应用程序的内容
代码清单 60:新创建的 ASP.NET 5 应用的内容
```js
///
......@@ -521,13 +521,13 @@ project.webroot 来自 project.json 文件,该文件是通过 require 语句
到目前为止,我们主要看到了如何利用大口来捆绑、缩小和翻译脚本和 CSS。这些都是很棒的特性,并且它从开发人员那里带走了很多手工工作。我们将这些结果直接包含到我们的 HTML 文件中,并将其发送到浏览器以执行他们的工作。
开发时,您实际上会编写代码。在创建下一个伟大应用程序的过程中,您可能会不断构建、捆绑或缩小代码。进行这些更新最终会产生新的文件,我们希望将这些文件包含在我们的页面中。然而,浏览器试图缓存尽可能多的静态内容。这是您的应用程序在生产周期中所需要的,因为您会看到到达服务器的请求越来越少,从而节省了服务器上的资源。在开发或升级生产中部署的应用程序期间,您可能希望通知浏览器,他们需要忽略他们拥有的缓存版本并获取最新版本。
开发时,您实际上会编写代码。在创建下一个伟大应用的过程中,您可能会不断构建、捆绑或缩小代码。进行这些更新最终会产生新的文件,我们希望将这些文件包含在我们的页面中。然而,浏览器试图缓存尽可能多的静态内容。这是您的应用在生产周期中所需要的,因为您会看到到达服务器的请求越来越少,从而节省了服务器上的资源。在开发或升级生产中部署的应用期间,您可能希望通知浏览器,他们需要忽略他们拥有的缓存版本并获取最新版本。
有几种技术,最常见的是要么在文件名中放一个版本号,要么在它后面添加一个唯一的 querystring,使它整体上是唯一的。
因为这是经常被请求的,所以有不同的大口插件试图解决这个常见的问题。
在插件的帮助下,我们可以完成我们的任务。在我们之前使用的 ASP.NET MVC 应用程序中(或者一个新的),我们可以通过将以下内容放入 Razor 页面的<头>部分来调整 **_Layout.cshtml** 文件。
在插件的帮助下,我们可以完成我们的任务。在我们之前使用的 ASP.NET MVC 应用中(或者一个新的),我们可以通过将以下内容放入 Razor 页面的<头>部分来调整 **_Layout.cshtml** 文件。
代码清单 65: _Layout.cshtml 头部
......
......@@ -125,10 +125,10 @@ fn 可以是串联、并联、串联和并联的组合或函数。
npm 作为构建工具?到目前为止,我们看到 npm 被用来下载和管理 now 插件。嗯,在网上可以找到一些文章,关于人们利用 npm 来做我们在这本书里谈到的所有事情。在这个不断变化的世界里,这可能会成为一种新的做事方式。就目前而言,大口仍然是一个伟大的新兴工具,微软的采用也表明了它的重要性。
到目前为止,网络开发人员做了很多努力来最小化和连接脚本或 CSS 文件。有了 HTTP 2,这将不再是必要的。根据一些消息来源,这样做甚至可能适得其反,并损害性能。因此,您可能需要修改您精心制作的大口文件,以跟上不断进步的网络技术和协议,从而最大限度地发挥应用程序的性能。
到目前为止,网络开发人员做了很多努力来最小化和连接脚本或 CSS 文件。有了 HTTP 2,这将不再是必要的。根据一些消息来源,这样做甚至可能适得其反,并损害性能。因此,您可能需要修改您精心制作的大口文件,以跟上不断进步的网络技术和协议,从而最大限度地发挥应用的性能。
现代浏览器(也经常被称为“常青树”浏览器,因为它们总是最新的)已经支持 HTTP 2。服务器软件也在迅速赶上潮流,在未来的几年里,我们将看到对这种改进协议的支持无处不在,因此请确保您的应用程序对此进行密切监控。
现代浏览器(也经常被称为“常青树”浏览器,因为它们总是最新的)已经支持 HTTP 2。服务器软件也在迅速赶上潮流,在未来的几年里,我们将看到对这种改进协议的支持无处不在,因此请确保您的应用对此进行密切监控。
这是一个较短的章节,因为很难预测未来。然而,我们可以预见,HTTP 2 将在未来几年迅速变大。(网络)应用程序的数量将会增加,我们会看到它们有不同的形状,就像在智能设备上打包成一个应用程序,有像 Ionic、Cordova 和 multiple . js 这样的东西。
这是一个较短的章节,因为很难预测未来。然而,我们可以预见,HTTP 2 将在未来几年迅速变大。(网络)应用的数量将会增加,我们会看到它们有不同的形状,就像在智能设备上打包成一个应用,有像 Ionic、Cordova 和 multiple . js 这样的东西。
我希望你喜欢读这本书。
\ No newline at end of file
......@@ -12,9 +12,9 @@
纱提供了资源管理器和作业监视器之间的角色逻辑分离,资源管理器决定任务应该在哪里运行,作业监视器报告任务进度。这种分离是 Hadoop 2 中新架构的核心驱动力,因为它允许作业管理任务分布在集群中,这意味着平台可以在更高的规模上运行。
资源管理器是集中式主组件,它通常运行在 Hadoop 集群中与 HDFS 名称节点相同的节点上。资源管理器作为一个服务运行,当它启动一个新的作业时,它会创建一个应用程序主模块——一个负责确保作业(可以是一个 MapReduce 程序或一个交互式 Spark 会话)成功运行的软件组件。
资源管理器是集中式主组件,它通常运行在 Hadoop 集群中与 HDFS 名称节点相同的节点上。资源管理器作为一个服务运行,当它启动一个新的作业时,它会创建一个应用主模块——一个负责确保作业(可以是一个 MapReduce 程序或一个交互式 Spark 会话)成功运行的软件组件。
当应用程序主节点有工作要做时,它们会与资源管理器一起请求资源(例如 MapReduce 中的地图任务),它们还会与节点管理器一起工作,节点管理器是 Hadoop 集群中每个数据节点上的计算服务,以便监控任务。图 9 显示了作业的组件如何在集群中分布。
当应用主节点有工作要做时,它们会与资源管理器一起请求资源(例如 MapReduce 中的地图任务),它们还会与节点管理器一起工作,节点管理器是 Hadoop 集群中每个数据节点上的计算服务,以便监控任务。图 9 显示了作业的组件如何在集群中分布。
![yarn-work](img/00013.jpeg)
......@@ -24,31 +24,31 @@
| ![](img/00010.gif) | 注意:纱容器在逻辑上类似于 Docker 容器,但是到目前为止 Docker 还没有与纱集成,这意味着任务不能被调度为作为 Docker 容器实例运行。 |
当任务容器运行时,它们与应用程序主服务器通信进度,应用程序主服务器与提交作业的客户端通信整体进度。纱线允许容器使用自己的协议进行通信,这允许纱线在不知道框架内部工作的情况下运行不同类型的作业。然而,应用程序主机必须使用纱协议与资源管理器通信。
当任务容器运行时,它们与应用主服务器通信进度,应用主服务器与提交作业的客户端通信整体进度。纱线允许容器使用自己的协议进行通信,这允许纱线在不知道框架内部工作的情况下运行不同类型的作业。然而,应用主机必须使用纱协议与资源管理器通信。
当所有任务容器都完成时,应用程序主机将向客户端和资源管理器标记整个作业为完成,以便应用程序主机使用的资源可以被释放并用于其他工作。
当所有任务容器都完成时,应用主机将向客户端和资源管理器标记整个作业为完成,以便应用主机使用的资源可以被释放并用于其他工作。
纱的一个关键特征是,应用程序主机本身运行在一个容器中,该容器可以托管在集群中的任何节点管理器上,这样大型集群的容量就不会受到资源管理器容量的限制(因为应用程序主机分布在集群的工作节点周围)。
纱的一个关键特征是,应用主机本身运行在一个容器中,该容器可以托管在集群中的任何节点管理器上,这样大型集群的容量就不会受到资源管理器容量的限制(因为应用主机分布在集群的工作节点周围)。
## 【MapReduce 如何在纱中工作
我们已经用`hadoop jar`命令行向纱提交了一些 MapReduce 作业。使用该命令,我们所做的就是指定包含我们想要运行的应用程序和我们自己的代码所期望的参数的 JAR 文件。这会将作业提交给运行在名称节点上的资源管理器,资源管理器会检查集群中的容量,并在其中一个数据节点上分配一个容器来运行作业的应用程序主机。
我们已经用`hadoop jar`命令行向纱提交了一些 MapReduce 作业。使用该命令,我们所做的就是指定包含我们想要运行的应用和我们自己的代码所期望的参数的 JAR 文件。这会将作业提交给运行在名称节点上的资源管理器,资源管理器会检查集群中的容量,并在其中一个数据节点上分配一个容器来运行作业的应用主机。
应用程序主机可以在任何数据节点上启动,因此注册过程会返回到资源管理器,然后资源管理器会通知客户端应用程序主机正在哪里运行。从那时起,客户端直接与运行在数据节点上的应用程序主机通信。
应用主机可以在任何数据节点上启动,因此注册过程会返回到资源管理器,然后资源管理器会通知客户端应用主机正在哪里运行。从那时起,客户端直接与运行在数据节点上的应用主机通信。
应用程序主机启动作业,作业使用自己的框架来确定要执行的计算任务。在我们的字数统计中,MapReduce 框架将生成多个地图任务——每个输入文件一个,一个 Reduce 任务一个。当任务运行时,应用程序主机向资源管理器请求新的容器分配。请求可以具体说明其要求,请求所需的内存和 CPU 数量,甚至是首选节点名或机架名。
应用主机启动作业,作业使用自己的框架来确定要执行的计算任务。在我们的字数统计中,MapReduce 框架将生成多个地图任务——每个输入文件一个,一个 Reduce 任务一个。当任务运行时,应用主机向资源管理器请求新的容器分配。请求可以具体说明其要求,请求所需的内存和 CPU 数量,甚至是首选节点名或机架名。
如果有可用的容量,资源管理器会识别应用程序应该使用哪个节点管理器,应用程序主节点会直接与该节点通信,以创建容器并启动任务。当任务正在运行时,应用程序主机监视它们,当有更多任务排队等待调度时,应用程序主机继续运行。
如果有可用的容量,资源管理器会识别应用应该使用哪个节点管理器,应用主节点会直接与该节点通信,以创建容器并启动任务。当任务正在运行时,应用主机监视它们,当有更多任务排队等待调度时,应用主机继续运行。
如果任何任务失败,应用程序主机将决定如何处理失败。这可能意味着通过对资源管理器的另一次调用来重新安排任务,或者,在多次失败的情况下,这可能意味着将整个作业标记为失败并退出应用程序。在应用程序主机和资源管理器之间的通信失败的情况下,如在数据节点失败的情况下,资源管理器本身可以终止应用程序
如果任何任务失败,应用主机将决定如何处理失败。这可能意味着通过对资源管理器的另一次调用来重新安排任务,或者,在多次失败的情况下,这可能意味着将整个作业标记为失败并退出应用。在应用主机和资源管理器之间的通信失败的情况下,如在数据节点失败的情况下,资源管理器本身可以终止应用
无论应用程序主机如何结束,资源管理器的工作都是整理应用程序的容器分配,以便计算资源可以用于其他容器,例如新的应用程序主机或由另一个应用程序启动的任务容器。
无论应用主机如何结束,资源管理器的工作都是整理应用的容器分配,以便计算资源可以用于其他容器,例如新的应用主机或由另一个应用启动的任务容器。
资源管理器是根据需要分配计算资源的核心组件。计算资源是有限的,这意味着可能会有一个时间点无法满足资源请求,而纱有一个可插拔的框架,允许不同的方法来满足请求。这是调度器组件,它是在整个集群级别配置的,目前有三种实现与 Hadoop 捆绑在一起。
最简单的实现是先进先出调度器,它纯粹根据哪个应用程序先请求来分配资源。如果您使用先进先出调度器向 Hadoop 集群提交大型作业,该作业将使用所有可用资源,直到它完成或达到不再需要所有资源的程度。
最简单的实现是先进先出调度器,它纯粹根据哪个应用先请求来分配资源。如果您使用先进先出调度器向 Hadoop 集群提交大型作业,该作业将使用所有可用资源,直到它完成或达到不再需要所有资源的程度。
当应用程序停止请求资源并释放现有资源时,队列中的下一个应用程序将启动。图 10 显示了两个大型作业和一个小型作业如何使用先进先出调度器运行。
当应用停止请求资源并释放现有资源时,队列中的下一个应用将启动。图 10 显示了两个大型作业和一个小型作业如何使用先进先出调度器运行。
![fifo](img/00014.jpeg)
......@@ -90,13 +90,13 @@
13:纱线资源管理器界面
资源管理器的默认视图是显示所有正在运行的作业,并链接到它们各自的应用程序主用户界面。请记住,作业的应用程序主节点作为容器在集群中的工作节点上运行,但是应用程序主节点将进度反馈给资源管理器。当您打开应用程序链接时,您将看到图 14 中的用户界面。
资源管理器的默认视图是显示所有正在运行的作业,并链接到它们各自的应用主用户界面。请记住,作业的应用主节点作为容器在集群中的工作节点上运行,但是应用主节点将进度反馈给资源管理器。当您打开应用链接时,您将看到图 14 中的用户界面。
![](img/00018.jpeg)
14:应用主界面
图 14 显示了应用程序运行的工作分解。在这种情况下,是第 2 章的`grep` MapReduce 作业,UI 显示地图数量,按状态减少任务。您可以通过跟踪链接并获得所有任务的列表,然后查看特定任务的日志,来深入了解更多细节,如图 15 所示。
图 14 显示了应用运行的工作分解。在这种情况下,是第 2 章的`grep` MapReduce 作业,UI 显示地图数量,按状态减少任务。您可以通过跟踪链接并获得所有任务的列表,然后查看特定任务的日志,来深入了解更多细节,如图 15 所示。
![](img/00019.jpeg)
......@@ -106,11 +106,11 @@
有了资源管理器和节点管理器 web 服务器,您还将获得很多关于机器和 Hadoop 设置的细节。您可以查看节点的硬件分配,查看 Hadoop 服务日志,以及从网络用户界面查看指标和配置,这些都值得深入了解。
在这一章中,我们看了 Hadoop 的计算部分,了解了 part 是如何工作的,以及 Hadoop 中资源协商的关键部分。纱线是一个通用的作业调度器,支持不同的应用程序框架——主要是 MapReduce,但也支持较新的应用程序类型,如 Spark 和 Tez。纱允许应用程序请求资源,它将满足基于集群的容量,它让应用程序决定他们需要哪些资源。
在这一章中,我们看了 Hadoop 的计算部分,了解了 part 是如何工作的,以及 Hadoop 中资源协商的关键部分。纱线是一个通用的作业调度器,支持不同的应用框架——主要是 MapReduce,但也支持较新的应用类型,如 Spark 和 Tez。纱允许应用请求资源,它将满足基于集群的容量,它让应用决定他们需要哪些资源。
纱的灵活性和可扩展性来自于主/从框架和关注点的分离。在主节点上,资源管理器的角色是接受来自客户端的作业请求,通过分配应用程序主节点来启动作业,以及响应来自正在运行的应用程序的资源请求。
纱的灵活性和可扩展性来自于主/从框架和关注点的分离。在主节点上,资源管理器的角色是接受来自客户端的作业请求,通过分配应用主节点来启动作业,以及响应来自正在运行的应用的资源请求。
应用程序主控在资源容器中运行(不是 Docker 容器!)放在数据节点上,这样,纱中的管理开销就分布在整个集群中。当请求资源时,可以将纱配置为使用各种调度策略,这意味着您可以将集群设置为使用基本的先进先出策略、固定容量策略或公平策略,在活动作业之间尽可能公平地共享计算。
应用主控在资源容器中运行(不是 Docker 容器!)放在数据节点上,这样,纱中的管理开销就分布在整个集群中。当请求资源时,可以将纱配置为使用各种调度策略,这意味着您可以将集群设置为使用基本的先进先出策略、固定容量策略或公平策略,在活动作业之间尽可能公平地共享计算。
我们还简要地注意到,纱资源管理器和节点管理器服务嵌入了网络服务器。网络用户界面告诉我们许多关于集群中节点的信息以及它们所做的工作,这意味着它们对管理和故障排除很有用。
......
......@@ -4,9 +4,9 @@ Hadoop Streaming 使用标准的输入和输出流与执行进程进行通信,
流允许您使用 MapReduce,而不必为 mappers 和 Reduce 编写 Java 代码。这对于已经投资非 Java 平台的用户尤其有吸引力。如果您有一个用 Python 编写的自定义分析代码库,或者您想在中编写 MapReduce 代码。NET,你可以用 Hadoop Streaming 做到这一点。您甚至可以混合和匹配,使用带有 C++缩减器的 Java 映射器或带有 Python 缩减器的 R 映射器。
流式作业是一种 MapReduce 作业,但作业任务的执行模式不同。它仍然从客户端提交给纱,并且仍然遵循纱架构,应用程序主开始管理作业。Hadoop 附带了一个标准的 JAR 作为驱动程序,我们通过`hadoop`命令传递我们想要流式传输的可执行文件的细节。
流式作业是一种 MapReduce 作业,但作业任务的执行模式不同。它仍然从客户端提交给纱,并且仍然遵循纱架构,应用主开始管理作业。Hadoop 附带了一个标准的 JAR 作为驱动程序,我们通过`hadoop`命令传递我们想要流式传输的可执行文件的细节。
当任务容器运行时,Java 虚拟机生成可执行进程。与应用程序主机的通信是在 Java 虚拟机中完成的,它充当了 Hadoop 和流可执行文件之间的桥梁。
当任务容器运行时,Java 虚拟机生成可执行进程。与应用主机的通信是在 Java 虚拟机中完成的,它充当了 Hadoop 和流可执行文件之间的桥梁。
`hadoop-streaming.jar`取四个参数(至少;可以使用更多参数配置作业),指定输入和输出目录以及要为映射器和缩减器运行的可执行文件。代码清单 20 显示了一个有效的 Hadoop Streaming 作业提交,它使用标准的 Linux shell 命令作为映射器和缩减器。
......@@ -36,7 +36,7 @@ Hadoop Streaming 使用标准的输入和输出流与执行进程进行通信,
`wc`命令以固定的顺序写入输出,显示输入的行数、字数和总字节数,这里我们有 2022 行,包含 75KB 存储空间中的 7600 个字。这是一个微不足道的例子,但它展示了流的力量——这里我们有一些由 Hadoop 生成的真实分析,我们根本不需要编写任何代码。
Hadoop Streaming 使用一个非常简单的接口与可执行的映射器和缩减器进行通信。请记住,所有数据都是作为键值对通过 Hadoop 传输的,这也适用于流式应用程序。输入从 Hadoop 以一系列制表符分隔的行的形式提供给可执行文件,其中:
Hadoop Streaming 使用一个非常简单的接口与可执行的映射器和缩减器进行通信。请记住,所有数据都是作为键值对通过 Hadoop 传输的,这也适用于流式应用。输入从 Hadoop 以一系列制表符分隔的行的形式提供给可执行文件,其中:
* 第一个制表符前的字符串是键。
* 第一个制表符后的字符串是值。
......@@ -153,9 +153,9 @@ Python 也是一种非常简洁的语言。完整的源代码在 GitHub 上的[
为了。NET 程序员,微软提供了一个模仿 Hadoop Java API 的库,让我们可以在其中构建 MapReduce 作业。NET,使用类似于 Java 中使用的结构。映射器和缩减器都有基类,我们可以用键和值对以类型安全的方式工作。
然而,这只是 Hadoop Streaming 的一个语法包装——最终,. NET 项目被构建为一个可执行文件,它以与普通控制台应用程序相同的方式通过标准输入和输出流进行读写。那个。NET API 也有一段时间没有刷新了,这意味着您必须决定依赖一个旧的 API 是否值得您从包装流接口中获得的价值。
然而,这只是 Hadoop Streaming 的一个语法包装——最终,. NET 项目被构建为一个可执行文件,它以与普通控制台应用相同的方式通过标准输入和输出流进行读写。那个。NET API 也有一段时间没有刷新了,这意味着您必须决定依赖一个旧的 API 是否值得您从包装流接口中获得的价值。
在本章中,我们将继续讨论 Hadoop 流和。NET 源代码在 GitHub 上的[六眼/Hadoop-简洁地说/dotnet](https://github.com/sixeyed/hadoop-succinctly/tree/master/dotnet) ,它有两个控制台应用程序——一个用于映射器,一个用于减速器。代码与 Python 变体基本相同——将为每个任务创建一个映射器实例,并将输入文件中的行输入到 **stdin** 中。
在本章中,我们将继续讨论 Hadoop 流和。NET 源代码在 GitHub 上的[六眼/Hadoop-简洁地说/dotnet](https://github.com/sixeyed/hadoop-succinctly/tree/master/dotnet) ,它有两个控制台应用——一个用于映射器,一个用于减速器。代码与 Python 变体基本相同——将为每个任务创建一个映射器实例,并将输入文件中的行输入到 **stdin** 中。
映射器类中的`Main()`方法循环通过 **stdin** ,同时有更多的行,如代码清单 27 中的代码。
......@@ -271,7 +271,7 @@ reducer 类以同样的方式工作,通过控制台输入流循环的`Main()`
借助流接口,我们使用自己选择的语言构建相同类型的 MapReduce 组件。不需要显式的驱动程序,因为 Hadoop 安装提供的`hadoop-streaming.jar`充当驱动程序。我们也可以用我们选择的语言编写映射器和缩减器,并且我们可以包含我们通常使用的任何单元测试工具。
因为流可执行文件只是控制台应用程序,所以我们也可以使用输入数据的子集运行集成测试——将单个文件馈送到映射器并捕获输出,该输出将作为减速器的输入进行馈送。而且,因为运行连接 Hadoop 和我们的流程的 Java 虚拟机会产生成本,所以使用流的决定将包括性能考虑。
因为流可执行文件只是控制台应用,所以我们也可以使用输入数据的子集运行集成测试——将单个文件馈送到映射器并捕获输出,该输出将作为减速器的输入进行馈送。而且,因为运行连接 Hadoop 和我们的流程的 Java 虚拟机会产生成本,所以使用流的决定将包括性能考虑。
然而,要注意流媒体应用的互操作性。Hadoop 和您的可执行文件之间的协议总是以字符串的形式传递数据,因此,如果您试图将非 Java 映射器与 Java reducer 混合,您必须确保您的映射器以预期的格式序列化键和值输出,以便 reducer 可以反序列化。
......@@ -300,7 +300,7 @@ reducer 类以同样的方式工作,通过控制台输入流循环的`Main()`
当此作业运行时,Hadoop 将以高复制因子(默认值为 10)将归档文件复制到 HDFS,目标是它已经位于运行作业任务的节点的本地。当任务运行时,它将归档文件提取到作业的工作目录中,这样您的可执行文件将在当前目录中找到它的依赖项。
当一个 Java MapReduce 任务在 Hadoop 中的一个节点上运行时,它首先创建一个 Java 虚拟机来运行构建映射器或 Reduce 的 JAR 文件。对于流应用程序,没有 Java 代码,但是 JVM 仍然会被创建,除非您使用系统命令,否则可执行文件还需要引导自己的运行时。加载可执行运行时和 JVM 的成本将影响作业的整体运行时。
当一个 Java MapReduce 任务在 Hadoop 中的一个节点上运行时,它首先创建一个 Java 虚拟机来运行构建映射器或 Reduce 的 JAR 文件。对于流应用,没有 Java 代码,但是 JVM 仍然会被创建,除非您使用系统命令,否则可执行文件还需要引导自己的运行时。加载可执行运行时和 JVM 的成本将影响作业的整体运行时。
评估这个成本可能很困难,因为您不能使用典型的插装技术——当您的插装代码运行时,运行时已经被加载,并且成本已经发生。这种差异通常并不重要,因为您选择使用流是出于非功能性的原因(拥有想要重用的现有逻辑,或者在非 Java 平台中拥有更丰富的经验)。然而,了解做这个决定的成本总是有用的。
......
......@@ -14,8 +14,8 @@ Hadoop 具有内在的可扩展性和丰富的可配置性,这意味着您可
主服务器和从服务器的硬件要求在以下方面有所不同:
* 主节点是一个关键组件。它需要可靠,所以它应该有硬件 RAID 来存储,即使它不需要大量的磁盘空间。作为名称节点,它维护 HDFS 文件命名空间(存储在群集上的所有文件块的位置和元数据),为了提高性能,它将这些信息保存在内存中。作为资源管理器,它是所有应用程序主机和客户端连接的中心联系点。名称节点和资源管理器服务具有多种功能,但 CPU 能力不是主要因素。
* 工作节点并不重要,因为 Hadoop 的架构考虑到了故障。作为 HDFS 数据节点,工作人员应该有大量的磁盘存储,并且不需要 RAID(HDFS 使用循环方法进行磁盘分配,对于典型的 Hadoop 工作负载,该方法的基准速度快于 RAID-0)。作为纱节点管理人员,工作人员应该有大量的中央处理器核心和大量的内存供应。如果您计划只运行 MapReduce 应用程序,每个任务将需要分配一个 CPU 内核和 1 GB 内存,您可以使用这些数据来粗略计算集群的容量。
* 主节点是一个关键组件。它需要可靠,所以它应该有硬件 RAID 来存储,即使它不需要大量的磁盘空间。作为名称节点,它维护 HDFS 文件命名空间(存储在群集上的所有文件块的位置和元数据),为了提高性能,它将这些信息保存在内存中。作为资源管理器,它是所有应用主机和客户端连接的中心联系点。名称节点和资源管理器服务具有多种功能,但 CPU 能力不是主要因素。
* 工作节点并不重要,因为 Hadoop 的架构考虑到了故障。作为 HDFS 数据节点,工作人员应该有大量的磁盘存储,并且不需要 RAID(HDFS 使用循环方法进行磁盘分配,对于典型的 Hadoop 工作负载,该方法的基准速度快于 RAID-0)。作为纱节点管理人员,工作人员应该有大量的中央处理器核心和大量的内存供应。如果您计划只运行 MapReduce 应用,每个任务将需要分配一个 CPU 内核和 1 GB 内存,您可以使用这些数据来粗略计算集群的容量。
服务器规格不断提高,但在撰写本文时,适合用作 Hadoop 从机的典型商用服务器将具有 12-16 个 CPU 内核、48-128 GB RAM 和最多 12 个磁盘,每个磁盘最多有 4 TB 的存储空间。合理的预算应该可以让您满足于拥有 48 GB 内存和 36 TB 存储的 16 核机器。
......@@ -71,13 +71,13 @@ Hadoop 具有在不停机的情况下跨集群重新平衡数据的功能,因
您可以运行命令`hadoop balancer`开始跨集群重新平衡数据,但是,为了节省集群容量,Hadoop 在决定数据块应该移动到哪里时使用运行平衡器的机器的计算能力,这意味着您应该在能够快速访问集群的快速机器上调用它。即便如此,重新平衡数万亿字节的数据也需要几天时间。
正如 HDFS 监控数据可用性和补救任何丢失的块一样,纱监控作业进度,并可以解决丢失任务和失败作业的问题。当任务运行时,它们由应用程序主节点负责,它们发送心跳消息的方式与数据节点向名称节点发送心跳的方式相同。
正如 HDFS 监控数据可用性和补救任何丢失的块一样,纱监控作业进度,并可以解决丢失任务和失败作业的问题。当任务运行时,它们由应用主节点负责,它们发送心跳消息的方式与数据节点向名称节点发送心跳的方式相同。
如果任务意外失败,或者心跳停止,应用程序主机会将任务标记为失败,并请求资源管理器(理想情况下,资源管理器运行在与任务失败的节点不同的节点上)提供另一个容器来重复失败的任务。
如果任务意外失败,或者心跳停止,应用主机会将任务标记为失败,并请求资源管理器(理想情况下,资源管理器运行在与任务失败的节点不同的节点上)提供另一个容器来重复失败的任务。
纱让你配置多少重试允许映射和减少任务。默认值允许四次任务重试,但是如果任何一个任务失败四次,应用程序将被标记为失败。这也是可配置的,这意味着您可以设置纱,以允许一定百分比的任务失败,同时保持作业运行。
纱让你配置多少重试允许映射和减少任务。默认值允许四次任务重试,但是如果任何一个任务失败四次,应用将被标记为失败。这也是可配置的,这意味着您可以设置纱,以允许一定百分比的任务失败,同时保持作业运行。
尽管是资源管理器的责任,运行的应用程序也发送心跳消息。如果应用程序主机以失败状态结束或停止发送心跳,资源管理器将结束应用程序,并使用新的应用程序主机重试。应用程序的重试次数也是可配置的,这意味着纱允许大量的调整,以确保短暂的故障不会阻止作业完成,坏的作业(可能是由于代码或数据的缺陷)不会阻塞集群。
尽管是资源管理器的责任,运行的应用也发送心跳消息。如果应用主机以失败状态结束或停止发送心跳,资源管理器将结束应用,并使用新的应用主机重试。应用的重试次数也是可配置的,这意味着纱允许大量的调整,以确保短暂的故障不会阻止作业完成,坏的作业(可能是由于代码或数据的缺陷)不会阻塞集群。
我们已经看到了 Hadoop 行为可配置的几个方面,我们可以调整大量开关来改变集群的特性。
......@@ -173,7 +173,7 @@ HDFS 配置属性允许您指定服务应该侦听的端口、数据传输是否
在本章中,我们更仔细地研究了 Hadoop 集群的细节。我们研究了主节点和从节点的硬件要求,以及 Hadoop 在不同大小的集群中的表现。因为 Hadoop 集群能够优雅地扩展,所以确定新实施规模的一个好方法是估计数据捕获率,并为已知时期内具有足够容量的集群做好规划。
我们看到了 Hadoop 节点如何相互通信,发送心跳和状态报告,我们还看到了这如何提高集群的可靠性。对于 HDFS,数据节点的丢失会触发其余节点之间的额外数据复制。对于纱,节点管理器的丢失意味着在该节点上运行的任务和应用程序将在集群上被重新调度。
我们看到了 Hadoop 节点如何相互通信,发送心跳和状态报告,我们还看到了这如何提高集群的可靠性。对于 HDFS,数据节点的丢失会触发其余节点之间的额外数据复制。对于纱,节点管理器的丢失意味着在该节点上运行的任务和应用将在集群上被重新调度。
最后,我们查看了 Hadoop 中的配置框架,并看到了一些我们可以覆盖的属性。Hadoop 操作中的所有关键决策点都有我们可以指定的设置,这意味着我们可以调整我们的集群,以最有效地满足我们的需求。
......
......@@ -6,7 +6,7 @@
虽然从头开始安装 Hadoop 并不是一项令人生畏的任务,但建立多节点集群要复杂得多,而且它为扩展提供了更大的表面积。如果您决定将 Hive 或 Spark 添加到您的集群中,那么当您有 10 个数据节点要部署并保持同步时,这并不是小事。Ambari 是解决这个问题的管理控制台,还有更多。
Ambari 是一个网络应用程序,旨在为您的 Hadoop 集群提供单一访问点。它有一个可扩展的体系结构,具有不断增长的组件库,提供管理、监控和使用集群的功能。除了提供 web 视图,它还公开了一个 REST API,用于自动访问您的集群。
Ambari 是一个网络应用,旨在为您的 Hadoop 集群提供单一访问点。它有一个可扩展的体系结构,具有不断增长的组件库,提供管理、监控和使用集群的功能。除了提供 web 视图,它还公开了一个 REST API,用于自动访问您的集群。
在管理领域,安巴里负责所有主要任务:
......
......@@ -6,7 +6,7 @@
[本 HBase 文档](http://hbase.apache.org/)涵盖了在本地安装和运行 HBase,因此我在此不再赘述,但是在本地运行 HBase 最简单的方法是使用 Docker。Docker Hub 上有几个 HBase 映像,包括我自己的一个,这是我为了配合本课程而构建的。
Docker 是一种应用程序容器技术。容器是一个快速、轻量级的计算单元,允许您在一台机器上运行多个负载。容器在概念上类似于虚拟机,但在磁盘、CPU 和内存使用方面要轻得多。Docker 运行在 Linux、OS/X 和 Windows 机器上。您可以在这里获得安装说明[。Docker Hub 是一个预建图像的公共注册中心,我为这本书准备的图像可以在](http://www.docker.com/)[这里](https://hub.docker.com/r/sixeyed/hbase-succinctly)找到。
Docker 是一种应用容器技术。容器是一个快速、轻量级的计算单元,允许您在一台机器上运行多个负载。容器在概念上类似于虚拟机,但在磁盘、CPU 和内存使用方面要轻得多。Docker 运行在 Linux、OS/X 和 Windows 机器上。您可以在这里获得安装说明[。Docker Hub 是一个预建图像的公共注册中心,我为这本书准备的图像可以在](http://www.docker.com/)[这里](https://hub.docker.com/r/sixeyed/hbase-succinctly)找到。
使用 Docker 容器的好处是,您可以用很少的开销加速和终止实例,并且您不需要担心任何软件或服务与您的开发机器冲突。
......
......@@ -19,7 +19,7 @@ HBase Java 客户端可在 Maven Central 存储库中获得,并且经过版本
```
使用 Java API,您可以从一个 Configuration 对象开始,该对象包含服务器的连接详细信息,当您为表或管理创建客户机对象时,可以使用该对象。当您创建一个配置对象时,默认情况下,它会在包含配置设置的正在运行的应用程序的资源中查找一个 hbase-site.xml 文件。
使用 Java API,您可以从一个 Configuration 对象开始,该对象包含服务器的连接详细信息,当您为表或管理创建客户机对象时,可以使用该对象。当您创建一个配置对象时,默认情况下,它会在包含配置设置的正在运行的应用的资源中查找一个 hbase-site.xml 文件。
hbase-site.xml 配置文件也存在于服务器上,您可以将相同的内容用于客户端连接—它指定了服务器端口和 Zookeeper 仲裁地址等关键细节。代码清单 22 显示了站点文件的一些示例属性:
......
......@@ -4,7 +4,7 @@ HBase 非常适合跨平台的解决方案,而节俭 API 是 Java API 的替
默认情况下,节俭服务器监听端口 9090,并且它已经在简洁的 Docker 映像上运行。
节俭比 REST 更轻量级,因此它可以提供更好的性能,但它并不那么用户友好。要使用节俭应用编程接口,在大多数情况下,您需要从源构建节俭,从公共生成到应用编程接口的绑定。描述接口的节俭文件,然后为您的客户端应用程序导入节俭传输和绑定。
节俭比 REST 更轻量级,因此它可以提供更好的性能,但它并不那么用户友好。要使用节俭应用编程接口,在大多数情况下,您需要从源构建节俭,从公共生成到应用编程接口的绑定。描述接口的节俭文件,然后为您的客户端应用导入节俭传输和绑定。
![](img/00013.jpeg)注意:节俭原料药记录在。节俭档案。该文件没有附带 HBase 二进制文件,因此您需要从源代码中获取正确的版本。对于版本 1.1.2,文件在 GitHub [这里](https://github.com/apache/hbase/blob/cc2b70cf03e3378800661ec5cab11eb43fafe0fc/hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift2/hbase.thrift)上。
......@@ -173,7 +173,7 @@ HappyBase 表对象上的 put()方法的工作方式很像 HBase Shell 中的 pu
```
put()方法仅限于单个行,但是 HappyBase 为批处理更新提供了一个有用的机制。这是 HBase 客户端的一个常见要求,尤其是在事件流应用程序中,您每秒可能会收到数百甚至数千个要在处理器中缓冲的事件。
put()方法仅限于单个行,但是 HappyBase 为批处理更新提供了一个有用的机制。这是 HBase 客户端的一个常见要求,尤其是在事件流应用中,您每秒可能会收到数百甚至数千个要在处理器中缓冲的事件。
HappyBase 中的 Batch 类允许您这样做,而无需编写定制代码来维护挂起更新的缓冲区。您可以从表中创建批处理对象,并在上下文管理器块中使用它。当块结束时,在批处理上调用 send()方法,该方法将所有更新发送到节俭服务器,如代码清单 46 所示:
......
......@@ -107,11 +107,11 @@ HTTP GET 请求相当于 HBase 外壳中的 GET 命令。您可以添加一个
您可以使用 cURL 做更多的事情,比如发送删除请求来删除数据,以及创建扫描仪来获取多行,但是语法变得很麻烦。在星际之门中使用 RESTful API 的包装器是一个更好的选择。
NuGet 是的包管理器。NET 应用程序,还有几个开源包是访问星际之门的包装器。微软有一个专门针对运行在 Azure 云上的 HBase 集群的包,还有一个来自作者“部落”的第三方包,用于一般地使用 Stargate。
NuGet 是的包管理器。NET 应用,还有几个开源包是访问星际之门的包装器。微软有一个专门针对运行在 Azure 云上的 HBase 集群的包,还有一个来自作者“部落”的第三方包,用于一般地使用 Stargate。
这个包很好地抽象了星际之门的内部,让你可以直观地处理 HBase 数据。它是 IoC 感知的(默认情况下使用自动调整),因此您可以轻松地调整 HTTP 设置并构建一个数据访问层,您可以模拟出来进行测试。
将该包及其依赖项添加到。NET 应用程序中,您可以使用代码清单 52 中的 NuGet 包管理器控制台命令:
将该包及其依赖项添加到。NET 应用中,您可以使用代码清单 52 中的 NuGet 包管理器控制台命令:
52:为星门添加一个 NuGet 引用
......@@ -120,7 +120,7 @@ NuGet 是的包管理器。NET 应用程序,还有几个开源包是访问星
```
在本书的 GitHub 存储库中,有一个. NET 控制台应用程序,它使用部落的客户端连接到星门,运行在简洁的 Docker 容器中。
在本书的 GitHub 存储库中,有一个. NET 控制台应用,它使用部落的客户端连接到星门,运行在简洁的 Docker 容器中。
要设置星门客户端,您需要配置服务器网址并构建容器。代码清单 53 展示了如何使用 Autofac 实现这一点:
......
......@@ -14,7 +14,7 @@
## 数据管理和存储
数据管理需求已经从传统的关系存储发展到关系和非关系存储,全方位的信息管理平台需要支持所有类型的数据。为了提供对任何数据的洞察,需要一个平台,为跨关系、非关系和流数据的数据管理提供一整套功能。该平台需要能够无缝地将数据从一种类型移动到另一种类型,并且能够监控和管理所有数据,而不管它是什么类型的数据或数据结构。这必须在应用程序不必担心规模、性能、安全性和可用性的情况下进行。
数据管理需求已经从传统的关系存储发展到关系和非关系存储,全方位的信息管理平台需要支持所有类型的数据。为了提供对任何数据的洞察,需要一个平台,为跨关系、非关系和流数据的数据管理提供一整套功能。该平台需要能够无缝地将数据从一种类型移动到另一种类型,并且能够监控和管理所有数据,而不管它是什么类型的数据或数据结构。这必须在应用不必担心规模、性能、安全性和可用性的情况下进行。
除了支持所有类型的数据之外,在非关系存储(如 Hadoop)和关系数据仓库之间来回移动数据也是大数据客户的主要使用模式之一。为了支持这种常见的使用模式,微软为存储在 Hadoop 和现有的 SQL Server 数据仓库环境(包括 SQL Server 并行数据仓库)中的数据之间的高速数据移动提供了连接器。
......@@ -34,7 +34,7 @@
对于 Windows Azure 上的服务,微软将通过 Azure 管理门户的易用组件实现 Hadoop 集群的无缝设置和配置,从而进一步降低部署障碍。
最后,他们不仅发布了基于开源的 Hadoop 发行版,还承诺将这些更新回馈给 Hadoop 社区。微软致力于提供与 Apache Hadoop 应用程序编程接口(APIs)100%的兼容性,以便为 Apache Hadoop 编写的应用程序应该在 Windows 上工作。
最后,他们不仅发布了基于开源的 Hadoop 发行版,还承诺将这些更新回馈给 Hadoop 社区。微软致力于提供与 Apache Hadoop 应用编程接口(APIs)100%的兼容性,以便为 Apache Hadoop 编写的应用应该在 Windows 上工作。
微软与 [Hortonworks](http://www.hortonworks.com/) 紧密合作,提交了一份正式提案,作为对 Apache 代码库的更改,在 Windows Azure 和 Windows Server 上贡献基于 Hadoop 的发行版。[<sup>【4】</sup>](12.html#_ftn4)此外,他们还在合作开发其他功能,如 Hive 连接,以及由微软和 Hortonworks 开发的创新 JavaScript 库,将被提议作为对 Apache 软件基金会的贡献。
......
......@@ -194,7 +194,7 @@ Reducer 相当于 ETL 范例的转换组件。它的工作是处理提供的数
使用压缩输入和压缩输出会带来一些性能影响,需要根据存储和网络流量考虑进行平衡。要在 HDInsight 中全面回顾这些注意事项,建议您阅读微软关于题为“Hadoop 中的压缩”的主题的白皮书(上面表格中的信息取自该白皮书)。[<sup>【17】</sup>](12.html#_ftn17)
映射器是作为标准的 C#控制台应用程序可执行文件构建的。为了让 Hadoop 作业能够使用它,它需要被加载到作业可以引用该文件的某个地方。Azure Blob 存储显然是处理这个问题的一个方便的地方。
映射器是作为标准的 C#控制台应用可执行文件构建的。为了让 Hadoop 作业能够使用它,它需要被加载到作业可以引用该文件的某个地方。Azure Blob 存储显然是处理这个问题的一个方便的地方。
加载数据和映射器后,使用 Hadoop 命令行来指定和启动作业。也可以通过 SDK 或 PowerShell 提交作业。
......
......@@ -14,11 +14,11 @@
### 为蜂巢建立一个 DSN
连接到 Hive 的先决条件是设置 Excel 可以引用的 64 位系统数据源名称(DSN)。搜索 ODBC 会出现两个应用程序:
连接到 Hive 的先决条件是设置 Excel 可以引用的 64 位系统数据源名称(DSN)。搜索 ODBC 会出现两个应用:
![](img/image010.png)
图 8: ODBC 应用程序
图 8: ODBC 应用
从这里,这将启动 ODBC 数据源管理员。在系统 DSN 下,选择“添加”。选择“创建新数据源”时,配置单元驱动程序被列为可用选项:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册