回顾我和编程之缘

回顾自己十六年来的编程经历,我很乐意分享我和计算机编程结缘的过程。 高中毕业的时候,我从邻居家借到一本Basic语言的书籍,我被它迷住了,那时候我没有计算机,只是在草稿纸上模仿书本上的例子进行四则运算和解方程运算。事实上我从小梦想是做一名数学家,所以我大学专业是数学与应用数学。那时候计算机在中国是热门专业,所以数学系也开了很多计算机的课程,我认真学了一个学期的C语言程序设计,我一直被计算机编程的能力震撼,那时候我知道Matlab和Mathematica可以调用C语言的类库进行非常复杂的数值运行,我在大学参加数学建模比赛就是用计算机算法去验证数学模型。 大二的时候我第一次接触Delphi,第一次接触Pascal语言,被它的简洁语法吸引,不过Delphi那时候已经走下坡路,微软的MFC已经蚕食它的市场份额,而Delphi的创始人安德斯海尔斯伯格也被比尔盖茨挖到微软。大二结束的时候我参加学校编程社团,第一次学习C#并且使用ASP.NET WebForm开发网站,从同学那里,我也了解C#的创始人海尔斯伯格的传奇经历,我被两者深刻吸引。 大学毕业的时候我很幸运加入一家有名的软件公司方正集团,我继续使用C#和.NET开发网站,那时候我独立开发了一个CMS系统,虽然很简单但是非常实用,后来我深入参与电子报纸和电子图书的算法设计和软件开发。移动互联网刚刚诞生的时候,我和另外一位工程师基于Mac版本的FBReader开发了ios版本的图书阅读器,那时候我第一次接触object-c。 我也喜欢linux,自己会安装linux操作系统来学习,所以我在工作之余自学了php语言,但是我更喜欢C#这门语言,所以我一直没有转移到其他开发语言。微软和我Windows的闭源一直是我心疼之痛,后来我接触开源Mono,这是.NET在linux的一个实现,但是Mono的重点在桌面和游戏开发。 我加入百度公司之后有机会在linux生态系统下进行软件开发,我们使用php语言和mysql,这段经历扩宽了我的技术视野,让我对编程语言有了更深刻的理解:语言大同小异,最核心的还是算法和数据结构,以为优秀的开发人员应该能同时使用多种编程语言。 离开百度之后,我加入一家初创企业,我负责组建团队并开发互联网产品和软件,选择公司技术栈的时候我面临在php和c#之间二选一。那时候.NET已经开源,Mono的作者也创立了新公司Xamarin,专注于使用C#开发跨平台的移动应用。加上结合公司的情况,我继续选择使用C#作为主开发语言,但是我们也使用mysql、memcached和Redis等技术。我们的第一个移动应用也用C#来开发,那时候是属于很前卫的选择,还好我们坚持了下来,因为到了2016年微软换CTO了,开始拥抱开源,紧接着是收购Xamarin,还有筹划.NET Core的开发。我一直关注.NET Core的进展,后来看到StackOverflow使用.NET Core2.1,他们极大提升了性能,于是我开始在我们的新开发产品中使用.NET Core,到了.NET Core3.1的时候开始将legacy code迁移到.NET Core。 这里不得不提一段我学习深度学习的插曲,2018年左右我认真学习了Michael A. Nielsen的《神经网络与深度学习》,并熟读第二章的多元微积分公式和证明,我甚至在纸上推导了全过程,这是我再次接触神经网络算法(大学数学建模的时候我学习过)。我似乎又回到了大学学习数学分析的时候,这本书写得非常好,作者从最根本最朴素的思想开始,结合实践进入深度神经网络,我认为这本书堪称神经网络的几何原本。我没有继续深入到深度学习中去,但是我认为它最根本的核心还在这本书里。也许哪一天,我还会重新捡回这段技术经历。

March 25, 2025

委托和接口的选择

A delegate design might be a better choice than an interface design if one or more of these conditions are true: • The interface defines only a single method. • Multicast capability is needed. • The subscriber needs to implement the interface multiple times. 如果满足以下一个或多个条件,委托设计可能比接口设计更好: • 接口仅定义一个方法。 • 需要多播功能。 • 订阅者需要多次实现该接口。

March 5, 2025

部署NextJS到Azure WebApp Deployment Error报错: cannot find module ../server/require-hook

当我将nextjs应用程序部署到azure web应用程序的时候报错:cannot find module ../server/require-hook。 我通过github-actions构建和部署成功完成,但是部署后,我在url 中收到错误,并且在azure日志流利发现这个错误。刚刚开始我不明白是什么原因造成的,因为“npm start”在我的本地机器上使用相同的 npm 版本构建和运行。 通过网上查找,发现是因为githhb的action默认不会把.next文件夹打包加入zip并且发布到azure。所以需要在默认的工作流基础上修改: 1、adding “startAzure”: “./node_modules/next/dist/bin/next start” in package.json; 还需要在azure应用程序网站的配置立加上 the startup command of the azure web app like “npm run startAzure” 2、添加这个到azure的 pipeline (在创建 zip了之后) - name: Zip artifact for deployment run: zip release.zip ./* -r - name: Add .next folder to zip artifact for deployment run: zip -r release.zip ".next"

February 27, 2025

MiniProfiler工具介绍

在日常开发中,应用程序的性能是我们需要关注的一个重点问题。当然我们有很多工具来分析程序性能:如:Zipkin等;但这些过于复杂,需要单独搭建。 MiniProfiler就是一款简单,但功能强大的应用新能分析工具;可以帮助我们定位:SQL性能问题、响应慢等问题。 MiniProfiler是一款针对.NET, Ruby, Go and Node.js的性能分析的轻量级程序。可以对一个页面本身,及该页面通过直接引用、Ajax、Iframe形式访问的其它页面进行监控,监控内容包括数据库内容,并可以显示数据库访问的SQL(支持EF、EF CodeFirst等 )。并且以很友好的方式展现在页面上。 MiniProfiler官网:http://miniprofiler.com/ MiniProfiler的一个特别有用的功能是它与数据库框架的集成。除了.NET原生的 DbConnection类,MiniProfiler还内置了对实体框架(Entity Framework)以及LINQ to SQL、RavenDb和MongoDB的支持。任何执行的Step都会包括当时查询的次数和所花费的时间。为了检测常见的错误,如N+1反模式,profiler将检测仅有参数值存在差异的多个查询。

June 26, 2024

数据访问策略: Dapper和Entity Framework混合应用

作者 Julie Lerman 你大概注意到了,自 2008 年以来,我写过许多关于 Entity Framework(即 Microsoft 对象关系映射器 (ORM))的文章,ORM 一直是主要的 .NET 数据访问 API。市面上还有许多其他 .NET ORM,但是有一个特殊类别因其强大的性能得到的关注最高,那就是微型 ORM。我听人提到最多的微型 ORM 是 Dapper。据不同的开发者说,他们使用 EF 和 Dapper 制定了混合解决方案,让每个 ORM 能够在单个应用程序中做它最擅长的事,这最终激发了我的兴趣,促使我在最近抽出时间来一探究竟。 在阅读大量文章和博客文章,与开发者聊过天并熟悉过 Dapper 后,我想与大家分享我的一些发现,尤其是和像我这样,可能听说过 Dapper 但并不知道它是什么或者并不知道它的工作原理的人分享,同时说说人们为什么这么喜欢它。需要提醒你的是,我根本不是什么专家。目前我只是为了满足我的好奇心而变得足够了解,并且希望激发你的兴趣,从而进一步探索。 为什么是 Dapper? Dapper 的历史十分有趣,它是从你可能再熟悉不过的资源中衍生的: Marc Gravell 和 Sam Saffron 在研究 Stack Overflow,解决此平台的性能问题时构建了 Dapper。考虑到 Stack Overflow 是一个流量极高的站点,那么必然存在性能上的问题。根据 Stack Exchange About 网页,在 2015 年,Stack Overflow 拥有 57 亿的网页浏览量。在 2011 年,Saffron 撰写过一篇关于他和 Gravell 所做的工作的博客文章,名为“我如何学会不再担忧和编写我自己的 ORM”(bit.ly/),这篇文章介绍了 Stack 当时存在的性能问题,该问题源于 LINQ to SQL 的使用。他在文中详细介绍了为什么编写自定义 ORM,其中 Dapper 就是优化 Stack Overflow 上的数据访问的答案。五年后的今天,Dapper 已被广泛使用并已成为开源软件。Gravell 和 Stack 及团队成员 Nick Craver 继续在 github.com/StackExchange/dapper-dot-net 上积极地管理项目。 ...

June 25, 2024

Entity Framework Core:一对多关系

当一个实体类型的任意数量的实体与相同或另一个实体类型的任意数量的实体相关联时,将使用多对多关系。 例如,Post 可以有多个关联的 Tags,并且每个 Tag 可以与任意数量的 Posts 关联。 了解多对多关系 多对多关系不同于一对多和一对一关系,因为它们不能仅使用外键以简单方式表示。 相反,需要其他实体类型来“联接”关系的两端。 这称为“联接实体类型”,并映射到关系数据库中的“联接表”。 此联接实体类型的实体包含外键值对,其中一对指向关系一端的实体,另一对指向关系另一端的实体。 因此,每个联接实体以及联接表中的每一行都表示关系中实体类型之间的一个关联。 EF Core 可以隐藏联接实体类型并在后台对其进行管理。 这允许以自然方式使用多对多关系的导航,从而根据需要在每一端添加或删除实体。 但是,了解后台发生的情况非常有用,以便其整体行为(尤其是映射关系数据库)有意义。 让我们从关系数据库架构设置开始,以表示帖子和标记之间的多对多关系: CREATE TABLE "Posts" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_Posts" PRIMARY KEY AUTOINCREMENT); CREATE TABLE "Tags" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_Tags" PRIMARY KEY AUTOINCREMENT); CREATE TABLE "PostTag" ( "PostsId" INTEGER NOT NULL, "TagsId" INTEGER NOT NULL, CONSTRAINT "PK_PostTag" PRIMARY KEY ("PostsId", "TagsId"), CONSTRAINT "FK_PostTag_Posts_PostsId" FOREIGN KEY ("PostsId") REFERENCES "Posts" ("Id") ON DELETE CASCADE, CONSTRAINT "FK_PostTag_Tags_TagsId" FOREIGN KEY ("TagsId") REFERENCES "Tags" ("Id") ON DELETE CASCADE); 在此架构中,PostTag 是联接表。 它包含两列:PostsId(指向 Posts 表的主键的外键)和 TagsId(指向 Tags 表的主键的外键)。 因此,此表中的每一行都表示一个 Post 和一个 Tag 之间的关联。 ...

June 23, 2024

Entity Framework Core:一对多关系

当单个实体与任意数量的其他实体关联时,将使用一对多关系。 例如,Blog 可以有多个关联的 Posts,但每个 Post 都只与一个 Blog 相关联。 本文档采用围绕大量示例展开的结构。 这些示例从常见情况着手,还引入了一些概念。 后面的示例介绍了不太常见的配置类型。 此处介绍了一个不错的方法,即了解前几个示例和概念,再根据特定需求转到后面的示例。 基于此方法,我们将从简单的“必需”和“可选”的一对多关系开始。 提示 可在 OneToMany.cs 中找到以下所有示例的代码。 必需的一对多 // Principal (parent) public class Blog { public int Id { get; set; } public ICollection<Post> Posts { get; } = new List<Post>(); // Collection navigation containing dependents } // Dependent (child) public class Post { public int Id { get; set; } public int BlogId { get; set; } // Required foreign key property public Blog Blog { get; set; } = null!; // Required reference navigation to principal } 一对多关系由以下部分组成: ...

June 21, 2024

Entity Framework Core:一对一关系

当一个实体与最多一个其他实体关联时,将使用一对一关系。 例如,Blog 有一个 BlogHeader,并且 BlogHeader 属于单个 Blog。 本文档采用围绕大量示例展开的结构。 这些示例从常见情况着手,还引入了一些概念。 后面的示例介绍了不太常见的配置类型。 此处介绍了一个不错的方法,即了解前几个示例和概念,再根据特定需求转到后面的示例。 基于此方法,我们将从简单的“必需”和“可选”的一对一关系开始。 可在 OneToOne.cs 中找到以下所有示例的代码。 必需的一对一 // Principal (parent) public class Blog { public int Id { get; set; } public BlogHeader? Header { get; set; } // Reference navigation to dependent } // Dependent (child) public class BlogHeader { public int Id { get; set; } public int BlogId { get; set; } // Required foreign key property public Blog Blog { get; set; } = null!; // Required reference navigation to principal } 一对一关系由以下部分组成: 主体实体上的一个或多个主键或备用键属性。 例如 Blog.Id。 依赖实体上的一个或多个外键属性。 例如 BlogHeader.BlogId。 (可选)引用依赖实体的主体实体上的引用导航。 例如 Blog.Header。 (可选)引用主体实体的依赖实体上的引用导航。 例如,BlogHeader.Blog。 提示 ...

June 20, 2024

Blazor server VS Blazor WebAssembly

Blazor WebAssembly 主要的 Blazor 托管模型在 WebAssembly 上的浏览器中运行客户端。 将 Blazor 应用、其依赖项以及 .NET 运行时下载到浏览器。 应用将在浏览器线程中直接执行。 UI 更新和事件处理在同一进程中进行。 应用资产作为静态文件部署到可为客户端提供静态内容的 Web 服务器或服务中。 Blazor WebAssembly:Blazor 应用在浏览器内部的 UI 线程上运行。 如果创建了 Blazor WebAssembly 应用进行部署,但没有后端 ASP.NET Core 应用来为其文件提供服务,那么该应用被称为独立 Blazor WebAssembly 应用。 如果创建了应用进行部署,但没有后端应用来为其文件提供服务,那么该应用被称为托管的 Blazor WebAssembly 应用。 托管的 Blazor WebAssembly Client 应用通常使用 Web API 调用或 SignalR(结合使用 ASP.NET Core SignalR 和 Blazor)通过网络与后端 Server 应用交互。 blazor.webassembly.js 脚本由框架和句柄提供: 下载 .NET 运行时、应用和应用依赖项。 初始化运行应用的运行时。 Blazor WebAssembly 托管模型具有以下优点: 没有 .NET 服务器端依赖项。 应用下载到客户端后即可正常运行。 可充分利用客户端资源和功能。 工作可从服务器转移到客户端。 无需 ASP.NET Core Web 服务器即可托管应用。 无服务器部署方案可行,例如通过内容分发网络 (CDN) 为应用提供服务的方案。 Blazor WebAssembly 托管模型具有以下局限性: ...

June 12, 2024

结合使用 ASP.NET Core SignalR 和 Blazor

本教程提供了使用 SignalR 和 Blazor 生成实时应用的基本工作经验。 本文适用于已经熟悉 SignalR 并正在寻求了解如何在 SignalR 应用中使用 Blazor 的开发人员。 有关 SignalR 和 Blazor 框架的详细指南,请参阅以下参考文档集和 API 文档: ASP.NET Core SignalR 概述 ASP.NET Core Blazor .NET API 浏览器 了解如何: 创建 Blazor 应用 添加 SignalR 客户端库 添加 SignalR 集线器 添加 SignalR 服务和 SignalR 中心的终结点 添加用于聊天的 Razor 组件代码 在本教程结束时,你将拥有一个正常运行的聊天应用。 先决条件 Visual Studio Visual Studio Code .NET CLI 具有“ASP.NET 和 Web 开发”工作负载的 Visual Studio 2022 或更高版本 示例应用 本教程不需要下载教程的示例聊天应用。 示例应用是按照本教程的步骤生成的最终工作应用。 查看或下载示例代码(如何下载) 创建 Blazor Web 应用 按照所选工具的指南进行操作: ...

June 12, 2024