数据访问策略: 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

写在第八个父亲节:反思自我少发火

父亲节,女儿很乖,儿子大闹,我又发了一轮火-_- 我们不算是鸡娃的家长,但是对子女有最基本的要求,为了引导和教育子女,我这段时间发现自己对小孩们发脾气的次数变多了。每次发完火之后,我知道这很不好,但是总是不能克制住自己,其实对小孩或者家人发火,只是情绪的宣泄,对谁都不好。我总结自己发火的点: 1、子女们的行为习惯。主要是生活习惯和本来应该养成的好习惯,有时候他们屡教不改,这方面是应该严厉、严格,但是不要动火,否则无济于事。 2、对于子女们的兴趣培养,比如小提琴,总是会有“恨铁不成刚”的想法。如果静下来想想,他们的水平已经远远在我之上,所以很多时候更多是自己的期望值太高。如果能认识到兴趣要坚持和长期培养,那么我确实应该要更有耐心,毕竟核心是要让他们感兴趣地坚持下去。 3、辅导子女们的学业过程。其实想想小孩子需要时间去成长,有时候我是以大人的要求去教育小孩,我应该给他们更多的时间来消化及成长。 我今天反思自己,就是希望自己能控制情绪,作为一个男人,应该能担当、沉住气,这样才能真的起到教育的作用。 “父母所遭受的文化和心理压力或伤害可能会传递到孩子身上。我绝不是危言耸听,我想提醒父母们,我们赋予孩子的一切中,有一半来自我们自己,因此,我们首先需要让自己变成身心健康的人。” 立帖为证,做好自己。

June 16, 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

git提交或克隆报错fatal: unable to access ‘https://github.com/tata20191003/autowrite.git/‘: Failed to connec

1.问题原因 报错信息: fatal: unable to access ‘https://github.com/xxx/autowrite.git/’: OpenSSL SSL_read: Connection was reset, errno 10054 1 2 又或者 fatal: unable to access ‘https://github.com/xxx/autowrite.git/’: Failed to connect to github.com port 443: Timed out 1 2 因为git在拉取或者提交项目时,中间会有git的http和https代理,但是我们本地环境本身就有SSL协议了,所以取消git的https代理即可,不行再取消http的代理。 后续 原因还有一个,当前代理网速过慢,所以偶尔会成功,偶尔失败。 2.解决方案 1.在项目文件夹的命令行窗口执行下面代码,然后再git commit 或git clone 取消git本身的https代理,使用自己本机的代理,如果没有的话,其实默认还是用git的 //取消http代理 git config –global –unset http.proxy //取消https代理 git config –global –unset https.proxy 1 2 3 4 2.科学上网(vpn) 这样就能提高服务器连接速度,能从根本解决 time out 443问题 原文链接:https://blog.csdn.net/good_good_xiu/article/details/118567249

June 10, 2024

EF Add-Migration总结

EF CodeFirst对数据库任何的操作,千万不要手工去修改。 解释:add-migration命令是code first migration中的关键命令之一。当您对领域域模型进行更改并需要将它们时添加到数据库中,您将创建一个新的迁移。这是通过Add-Migration命令完成的。用最简单的形式,你只需要提供迁移名称 展现形式:命令将您的更改构建到一个cs文件中。这个cs文件与配置文件放在同一个文件夹中,服务于您要瞄准的DbContext 1.常用的命令: Add-Migration 、 Update-DataBase 、 Script-Migration (1)vs的程序包管理控制台输入 get-help Add-Migration -detailed以查看详细信息 Add-Migration [-Name] :指定自定义脚本 的名字 [-Force] [-ProjectName ] :如果要重新构建现有迁移,必须使用-Force参数。然而,只有在迁移尚未应用到数据库时,才能重新构建框架。否则你 需要回复到要重新构建的迁移之前的迁移 [-StartUpProjectName ] :是从 解决方案资源管理器中选择一个项目 作为启动项目。如果我们忽略的话,就会默认为解决方案资源管理器中的启动项目。 [-ConfigurationTypeName ] :项目中有多个DbContext,那么您需要指出哪个数据库会更新。这可以用-ConfigurationTypeName做。ConfigurationTypeName方法是迁移文件夹中配置类的名称。 [-ConnectionStringName ] :从应用程序的配置文件中指定要使用的连接字符串的名字。我们用两个参数-ConnectionString -ConnectionProviderName ,或者用这样一个参数代替 [-IgnoreChanges] :假设目标数据库模式与当前的模型是一致的。构建一个空迁移和对应的空的迁移文件,忽略在当前模型中检测到的任何挂起的更改。可用于创建初始的空迁移,以支持对现有数据库的迁移。 [-AppDomainBaseDirectory ]:指定用于运行数据迁移代码的app-domain的路径,从而app-domain 可以找到所有需要的程序集。这是一个高级选项,只有当解决方案包含多个项目时才会需要。这样的话,context和configuration所需要的程序集就不仅仅从那些包含context和包含migrations的项目中获取 CommonParameters Add-Migration (你的迁移文件名称) 若在一个项目里,操作多个DbConext的方法则需要指定context名称 add-migration 迁移名称 -c ConfigurationDbContext update-database -c ConfigurationDbContext

June 8, 2024

[转]MediatR知多少

原文:https://www.cnblogs.com/sheng-jie/p/10280336.html 引言 首先不用查字典了,词典查无此词。猜测是作者笔误将Mediator写成MediatR了。废话少说,转入正题。 先来简单了解下这个开源项目MediatR(作者Jimmy Bogard,也是开源项目AutoMapper的创建者,在此表示膜拜): Simple mediator implementation in .NET. In-process messaging with no dependencies. Supports request/response, commands, queries, notifications and events, synchronous and async with intelligent dispatching via C# generic variance. .NET中的简单中介者模式实现,一种进程内消息传递机制(无其他外部依赖)。 支持以同步或异步的形式进行请求/响应,命令,查询,通知和事件的消息传递,并通过C#泛型支持消息的智能调度。 如上所述,其核心是一个中介者模式的.NET实现,其目的是消息发送和消息处理的解耦。它支持以单播和多播形式使用同步或异步的模式来发布消息,创建和侦听事件。 中介者模式既然是对中介者模式的一种实现,那么我们就有必要简要介绍下中介者这个设计模式,以便后续展开。 中介者模式类图 中介者模式:用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互。 看上面的官方定义可能还是有点绕,那么下面这张图应该能帮助你对中介者模式有个直观了解。 使用中介模式,对象之间的交互将封装在中介对象中。对象不再直接相互交互(解耦),而是通过中介进行交互。这减少了对象之间的依赖性,从而减少了耦合。 那其优缺点也在图中很容易看出: 优点:中介者模式的优点就是减少类间的依赖,把原有的一对多的依赖变成了一对一的依赖,同事类只依赖中介者,减少了依赖,当然同时也降低了类间的耦合 缺点:中介者模式的缺点就是中介者会膨胀得很大,而且逻辑复杂,原本N个对象直接的相互依赖关系转换为中介者和同事类的依赖关系,同事类越多,中介者的逻辑就越复杂。 Hello MeidatR 在开始之前,我们先来了解下其基本用法。 单播消息传输 单播消息传输,也就是一对一的消息传递,一个消息对应一个消息处理。其通过IRequest来抽象单播消息,用IRequestHandler进行消息处理。 //构建 消息请求 public class Ping : IRequest { } //构建 消息处理 public class PingHandler : IRequestHandler<Ping, string> { public Task Handle(Ping request, CancellationToken cancellationToken) { return Task.FromResult(“Pong”); } } //发送 请求 var response = await mediator.Send(new Ping()); Debug.WriteLine(response); // “Pong” ...

June 5, 2024