diff --git a/Docs/Jupter笔记.001.入门说明.ipynb b/Docs/Jupter笔记.001.入门说明.ipynb deleted file mode 100644 index 88934f3..0000000 --- a/Docs/Jupter笔记.001.入门说明.ipynb +++ /dev/null @@ -1,895 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "Jupyter NoteBook 简单入门\n", - "==============================\n", - "\n", - "使用 Jupyter NoteBook 形式,优点是代码执行和 Markdown 文档放在同一个文件中,并可以交替显示和分段执行代码。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "## 显式声明使用 C# 语言\n", - "+ csharp\n", - "+ fsharp\n", - "+ pwsh" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "#!csharp" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "## C# 中的引用\n", - "+ 导入程序文件\n", - " > 可以导入多种文件,包括 .cs .csc .fc .js等,语法为` #!import /path/to/file ` \n", - "+ 引用本机 Dll 文件\n", - " > 可以导入本机编译好的dll文件,语法为 `#!import /path/to/file`\n", - "+ 引用 Nuget 包\n", - "+ > 默认包源下,可以导入nuget,当然也可以设置包源,语法为 `#r 包名,可选版本号`" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "## C# 中的引用\n", - "+ 导入程序文件\n", - " > 可以导入多种文件,包括 .cs .csc .fc .js等,语法为` #!import /path/to/file ` " - ] - }, - { - "cell_type": "code", - "execution_count": 63, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
MultiThreadingStudy.Core.Person
Id
1
Name小张
Address上海无名路1号
Age
28
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
MultiThreadingStudy.Core.Person
Id
1
Name小张
Address上海无名路1号
Age
28
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#! import \"..\\MultiThreadingStudy.Core\\Person.cs\"\n", - "\n", - "Person p = new Person()\n", - "{\n", - " Id=1,\n", - " Name=\"小张\",\n", - " Address=\"上海无名路1号\",\n", - " Age = 28\n", - "};\n", - "//在NoteBook中,可以格式化显示(Notebook提供) C#对象:使用 display(对象); 如果在代码结尾的话,可以直接写 C#对象。\n", - "display(p);\n", - "\n", - "//代码结尾的话,直接写 对象\n", - "p" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
{ Name = xx, Agx = 33 }
Namexx
Agx
33
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "var x = new {Name=\"xx\",Agx=33};\n", - "display(x);" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ 引用本机 Dll 文件\n", - " > 可以导入本机编译好的dll文件,语法为 `#!import /path/to/file`" - ] - }, - { - "cell_type": "code", - "execution_count": 67, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
MultiThreadingStudy.Core.Person
Id
2
Name本山
Address
<null>
Age
55
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#r \"..\\MultiThreadingStudy.Core\\bin\\Debug\\netstandard2.1\\MultiThreadingStudy.Core.dll\"\n", - "\n", - "using MultiThreadingStudy.Core;\n", - "\n", - "MultiThreadingStudy.Core.Person personA= new MultiThreadingStudy.Core.Person()\n", - "{\n", - " Id=2,\n", - " Name=\"本山\",\n", - " Age=55\n", - "};\n", - "\n", - "personA" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ 引用 Nuget 包" - ] - }, - { - "cell_type": "code", - "execution_count": 136, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "{\"Id\":2,\"Name\":\"newtonsoft类库\",\"Age\":6}" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "//安装库的最新版本\n", - "#r \"nuget:newtonsoft.json\"\n", - "var jsonObj = new {Id=2,Name=\"newtonsoft类库\", Age=6};\n", - "\n", - "//使用库\n", - "var jsonText = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj);\n", - "jsonText" - ] - }, - { - "cell_type": "code", - "execution_count": 137, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "{\"Id\":2,\"Name\":\"System.Text.Json\\u7C7B\\u5E93\",\"Age\":6}" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "//安装库的指定版本\n", - "#r \"nuget:System.Text.Json,4.7.2\"\n", - "\n", - "//使用库\n", - "var jsonObj2 = new {Id=2,Name=\"System.Text.Json类库\", Age=6};\n", - "var jsonText2 = System.Text.Json.JsonSerializer.Serialize(jsonObj2);\n", - "jsonText2" - ] - }, - { - "cell_type": "code", - "execution_count": 163, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
Restore sources
Installed Packages
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "//安装最新的预览版库\n", - "#r \"nuget:xunit,*-*\"\n", - "\n", - "using Xunit;\n", - "using Xunit.Abstractions;\n", - "using Xunit.Sdk;\n", - "\n", - "public class UnitTest1\n", - "{\n", - " [Fact]\n", - " public void Test1()\n", - " {\n", - " Assert.True(true, \"xxxx\");\n", - " }\n", - "}" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "## Nuget 包源管理\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ 默认 Nuget 包源\n", - " > 默认包源可能是:https://api.nuget.org/v3/index.json 使用默认包源的话,可以不添加包源引用。当然也可以添加。" - ] - }, - { - "cell_type": "code", - "execution_count": 165, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
Restore sources
Installed Packages
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#r \"nuget:AutoFixture.Xunit2\"" - ] - }, - { - "cell_type": "code", - "execution_count": 167, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
Restore sources
Installed Packages
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "//也可以指定默认包源\n", - "#i \"nuget:https://api.nuget.org/v3/index.json\"\n", - "\n", - "#r \"nuget:AutoFixture.Xunit2\"" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ 本机包源 Nuget" - ] - }, - { - "cell_type": "code", - "execution_count": 158, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
Restore sources
Installed Packages
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "//添加本地包源\n", - "#i \"nuget:C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\\"\n", - "\n", - "//使用包源\n", - "#r \"nuget:xunit\"\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ 经过身份验证的Nuget包源\n", - " > 不能直接引用验证包源,可以通过将源的 PAT 放入用户级 nuget.config 文件来访问经过身份验证的源" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "## 内建魔术命令" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ #!about 显示有关内核版本的信息" - ] - }, - { - "cell_type": "code", - "execution_count": 84, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "

.NET Interactive

© 2020 Microsoft Corporation

Version: 1.0.415202+b72e199d0d854bd532a8103ce626a5aab4a71c07

Library version: 1.0.0-beta.23152.2+b72e199d0d854bd532a8103ce626a5aab4a71c07

Build date: 2023-03-08T16:15:05.1062967Z

https://github.com/dotnet/interactive

" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#!about" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ #!lsmagic 列出可用的魔术命令,包括可能已通过扩展安装的命令" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "#!lsmagic" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ #!time 显示执行时间" - ] - }, - { - "cell_type": "code", - "execution_count": 92, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Wall time: 0.3225ms" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#!time" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ -h 参数 显示命令的帮助信息" - ] - }, - { - "cell_type": "code", - "execution_count": 104, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Description:\r\n", - " Time the execution of the following code in the submission.\r\n", - "\r\n", - "Usage:\r\n", - " #!time [options]\r\n", - "\r\n", - "Options:\r\n", - " -?, -h, --help Show help and usage information\r\n", - "\r\n", - "\r\n" - ] - } - ], - "source": [ - "#!time -h" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".NET (C#)", - "language": "C#", - "name": ".net-csharp" - }, - "polyglot_notebook": { - "kernelInfo": { - "defaultKernelName": "csharp", - "items": [ - { - "aliases": [ - "c#", - "C#" - ], - "languageName": "C#", - "name": "csharp" - }, - { - "aliases": [ - "frontend" - ], - "languageName": null, - "name": "vscode" - }, - { - "aliases": [ - "js" - ], - "languageName": "JavaScript", - "name": "javascript" - }, - { - "aliases": [], - "name": "webview" - }, - { - "aliases": [], - "languageName": null, - "name": ".NET" - } - ] - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/Docs/Jupter笔记.002.连接数据库.ipynb b/Docs/Jupter笔记.002.连接数据库.ipynb deleted file mode 100644 index 4836943..0000000 --- a/Docs/Jupter笔记.002.连接数据库.ipynb +++ /dev/null @@ -1,655 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "连接数据库\n", - "==============================\n", - "连接到SQL Server,并操作数据。 " - ] - }, - { - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ 引用操作类库" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "#r \"nuget:Microsoft.Dotnet.Interactive.SqlServer,*-*\"" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ 连接到SQL Server\n", - " > 数据库连接命令为 `#!connect` 查看连接帮助 `#!connect -h`" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "#!connect -h\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "> 连接到本机SQL Server, 特别注意的是 --kernel-name 指定名称,后面的SQL操作均需要使用:sql-{{kernel-name}}的值\n", - "> 比如 --kernel-name Demo, 则该SQL连接的kernel名称为 sql-Demo, 使用 #!sql-Demo 进行引用" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Kernel added: #!sql-Demo" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#!connect mssql \"server=.\\SQL2008;uid=sa;pwd=gly-bicijinlian;database=Demo;Encrypt=True;TrustServerCertificate=True;\" --kernel-name Demo\n", - "\n", - "//重复执行会抛出错误,目前没有找到解决方法\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ 使用连接\n", - " 一种方法是:在右下角,切换 Kernel, 由 `csharp - C# Script` 换成 由--kernel-name指定值生成的 `sql-Demo - T-SQL`" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "dotnet_interactive": { - "language": "sql-Demo" - }, - "polyglot_notebook": { - "kernelName": "sql-Demo" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(4 行受到影响)" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/csv": [ - "Id,Name,Age\r\n", - "1,张三,20\r\n", - "2,李四,30\r\n", - "3,三丰,300\r\n", - "4,小龙子,50\r\n" - ], - "text/html": [ - "
IdNameAge
1
张三
20
2
李四
30
3
三丰
300
4
小龙子
50
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "SELECT * from Test" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "> 推荐的是下面的方法:即使用 `#!sql-Demo` ,后面直接写SQL语句,不用切换 kernel " - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(4 行受到影响)" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/csv": [ - "Id,Name,Age\r\n", - "1,张三,20\r\n", - "2,李四,30\r\n", - "3,三丰,300\r\n", - "4,小龙子,50\r\n" - ], - "text/html": [ - "
IdNameAge
1
张三
20
2
李四
30
3
三丰
300
4
小龙子
50
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#!sql-Demo\n", - "SELECT * from Test" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "## 使用 EF Core" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ 新连接,添加 --create-dbcontext 参数" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/markdown": [ - "Scaffolding a `DbContext` and initializing an instance of it called `DemoEF` in the C# kernel." - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
Installed Packages
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Security Warning: The negotiated TLS 1.0 is an insecure protocol and is supported for backward compatibility only. The recommended protocol version is TLS 1.2 and later.\r\n" - ] - }, - { - "data": { - "text/plain": [ - "Kernel added: #!sql-DemoEF" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#!connect mssql \"server=.\\SQL2008;uid=sa;pwd=gly-bicijinlian;database=Demo;Encrypt=True;TrustServerCertificate=True;\" --create-dbcontext --kernel-name DemoEF " - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "上面的连接操作,会执行下面的任务:\n", - "搭建EFCore基架,并初始化 DBContext 的实例: DemoEF\n", - "安装包相关Nuget包,详情见输出\n", - "添加新的子内核 #!sql-DemoEF" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ 使用EFCore连接,操作数据" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(4 行受到影响)" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/csv": [ - "Id,Name,Age\r\n", - "1,张三,20\r\n", - "2,李四,30\r\n", - "3,三丰,300\r\n", - "4,小龙子,50\r\n" - ], - "text/html": [ - "
IdNameAge
1
张三
20
2
李四
30
3
三丰
300
4
小龙子
50
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#!sql-DemoEF\n", - "SELECT * from Test" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "source": [ - "+ 程序中使用EF Core连接" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
indexvalue
0
Submission#4+Test
Id
1
Name张三
Age
20
1
Submission#4+Test
Id
2
Name李四
Age
30
2
Submission#4+Test
Id
3
Name三丰
Age
300
3
Submission#4+Test
Id
4
Name小龙子
Age
50
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
-1
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "//连接建立后,执行环境中就有了相关的类:DBContext等\n", - "DemoEFContext context = new DemoEFContext();\n", - "var t = context.Tests.ToList();\n", - "display(t);\n", - "\n", - "FormattableString fs = $\"select * from Test;\";\n", - "var c = context.Database.ExecuteSql(fs);\n", - "display(c);" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".NET (C#)", - "language": "C#", - "name": ".net-csharp" - }, - "polyglot_notebook": { - "kernelInfo": { - "defaultKernelName": "csharp", - "items": [ - { - "aliases": [], - "name": "csharp" - } - ] - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/Docs/Jupyter笔记.1.1.入门说明.ipynb b/Docs/Jupyter笔记.1.1.入门说明.ipynb new file mode 100644 index 0000000..ce2cebd --- /dev/null +++ b/Docs/Jupyter笔记.1.1.入门说明.ipynb @@ -0,0 +1,635 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "Jupyter笔记 简单入门\n", + "==============================" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "使用 Jupyter NoteBook 形式,优点是代码执行和 Markdown 文档放在同一个文件中,并可以交替显示和分段执行代码。" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 显式声明使用 C# 语言\n", + "+ csharp\n", + "+ fsharp\n", + "+ pwsh" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#!csharp" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## C# 中的引用\n", + "+ 导入程序文件\n", + " > 可以导入多种文件,包括 .cs .csc .fc .js等,语法为` #!import /path/to/file ` \n", + "+ 引用本机 Dll 文件\n", + " > 可以导入本机编译好的dll文件,语法为 `#!import /path/to/file`\n", + "+ 引用 Nuget 包\n", + "+ > 默认包源下,可以导入nuget,当然也可以设置包源,语法为 `#r 包名,可选版本号`" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## C# 中的引用\n", + "+ 导入程序文件\n", + " > 可以导入多种文件,包括 .cs .csc .fc .js等,语法为` #!import /path/to/file ` " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#! import \"..\\MultiThreadingStudy.Core\\Person.cs\"\n", + "\n", + "Person p = new Person()\n", + "{\n", + " Id=1,\n", + " Name=\"小张\",\n", + " Address=\"上海无名路1号\",\n", + " Age = 28\n", + "};\n", + "//在NoteBook中,可以格式化显示(Notebook提供) C#对象:使用 display(对象); 如果在代码结尾的话,可以直接写 C#对象。\n", + "display(p);\n", + "\n", + "//代码结尾的话,直接写 对象\n", + "p" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var x = new {Name=\"xx\",Agx=33};\n", + "display(x);" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "+ 引用本机 Dll 文件\n", + " > 可以导入本机编译好的dll文件,语法为 `#!import /path/to/file`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#r \"..\\MultiThreadingStudy.Core\\bin\\Debug\\netstandard2.1\\MultiThreadingStudy.Core.dll\"\n", + "\n", + "using MultiThreadingStudy.Core;\n", + "\n", + "MultiThreadingStudy.Core.Person personA= new MultiThreadingStudy.Core.Person()\n", + "{\n", + " Id=2,\n", + " Name=\"本山\",\n", + " Age=55\n", + "};\n", + "\n", + "personA" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "+ 引用 Nuget 包" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "//安装库的最新版本\n", + "#r \"nuget:newtonsoft.json\"\n", + "var jsonObj = new {Id=2,Name=\"newtonsoft类库\", Age=6};\n", + "\n", + "//使用库\n", + "var jsonText = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj);\n", + "jsonText" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "//安装库的指定版本\n", + "#r \"nuget:System.Text.Json,4.7.2\"\n", + "\n", + "//使用库\n", + "var jsonObj2 = new {Id=2,Name=\"System.Text.Json类库\", Age=6};\n", + "var jsonText2 = System.Text.Json.JsonSerializer.Serialize(jsonObj2);\n", + "jsonText2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "//安装最新的预览版库\n", + "#r \"nuget:xunit,*-*\"\n", + "\n", + "using Xunit;\n", + "using Xunit.Abstractions;\n", + "using Xunit.Sdk;\n", + "\n", + "public class UnitTest1\n", + "{\n", + " [Fact]\n", + " public void Test1()\n", + " {\n", + " Assert.True(true, \"xxxx\");\n", + " }\n", + "}" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## Nuget 包源管理\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "+ 默认 Nuget 包源\n", + " > 默认包源可能是:https://api.nuget.org/v3/index.json 使用默认包源的话,可以不添加包源引用。当然也可以添加。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#r \"nuget:AutoFixture.Xunit2\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "//也可以指定默认包源\n", + "#i \"nuget:https://api.nuget.org/v3/index.json\"\n", + "\n", + "#r \"nuget:AutoFixture.Xunit2\"" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "+ 本机包源 Nuget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "//添加本地包源\n", + "#i \"nuget:C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\\"\n", + "\n", + "//使用包源\n", + "#r \"nuget:xunit\"\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "+ 经过身份验证的Nuget包源\n", + " > 不能直接引用验证包源,可以通过将源的 PAT 放入用户级 nuget.config 文件来访问经过身份验证的源" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 内建魔术命令" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "+ #!about 显示有关内核版本的信息" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#!about" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "+ #!lsmagic 列出可用的魔术命令,包括可能已通过扩展安装的命令" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#!lsmagic" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "+ #!time 显示执行时间" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#!time" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "+ -h 参数 显示命令的帮助信息" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#!time -h" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [ + "c#", + "C#" + ], + "languageName": "C#", + "name": "csharp" + }, + { + "aliases": [ + "frontend" + ], + "languageName": null, + "name": "vscode" + }, + { + "aliases": [ + "js" + ], + "languageName": "JavaScript", + "name": "javascript" + }, + { + "aliases": [], + "name": "webview" + }, + { + "aliases": [], + "languageName": null, + "name": ".NET" + }, + { + "aliases": [], + "languageName": "KQL", + "name": "kql" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Docs/Jupyter笔记.1.2.连接数据库.ipynb b/Docs/Jupyter笔记.1.2.连接数据库.ipynb new file mode 100644 index 0000000..d2c05d9 --- /dev/null +++ b/Docs/Jupyter笔记.1.2.连接数据库.ipynb @@ -0,0 +1,546 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "连接数据库\n", + "============================== " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "连接到SQL Server,并操作数据。" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 引用操作类库" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#r \"nuget:Microsoft.Dotnet.Interactive.SqlServer,*-*\"" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 连接到SQL Server" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "### 数据库连接命令" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "#### 命令概述: 使用帮助参数" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "数据库连接命令为 `#!connect` 查看连接帮助 `#!connect -h`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#!connect -h" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "#### 连接到本机SQL Server" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "1. 建立连接" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "> 连接到本机SQL Server, 特别注意的是 --kernel-name 指定名称,后面的SQL操作均需要使用:sql-{{kernel-name}}的值\n", + "> 比如 --kernel-name Demo, 则该SQL连接的kernel名称为 sql-Demo, 使用 #!sql-Demo 进行引用" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#!connect mssql \"server=.\\SQL2008;uid=sa;pwd=gly-bicijinlian;database=Demo;Encrypt=True;TrustServerCertificate=True;\" --kernel-name Demo\n", + "//重复执行会抛出错误,目前没有找到解决方法" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "2. 使用连接: 方式一" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "> 在右下角,切换 Kernel, 由 `csharp - C# Script` 换成 由--kernel-name指定值生成的 `sql-Demo - T-SQL`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "sql-Demo" + }, + "polyglot_notebook": { + "kernelName": "sql-Demo" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "SELECT * from Test" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "2. 使用连接:方式二(推荐)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "> 使用 `#!sql-Demo` ,后面直接写SQL语句,不用切换 kernel " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#!sql-Demo\n", + "SELECT * from Test" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 使用 EF Core" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "### 新连接: 添加 --create-dbcontext 参数" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#!connect mssql \"server=.\\SQL2008;uid=sa;pwd=gly-bicijinlian;database=Demo;Encrypt=True;TrustServerCertificate=True;\" --create-dbcontext --kernel-name DemoEF " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "上面的连接操作,会执行下面的任务:\n", + "+ 搭建EFCore基架,并初始化 DBContext 的实例: DemoEF\n", + "+ 安装包相关Nuget包,详情见输出\n", + "+ 添加新的子内核 #!sql-DemoEF" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "### 使用EFCore连接: 操作数据" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "#### 类SQL脚本方式" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#!sql-DemoEF\n", + "SELECT * from Test" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "#### C#程序中使用EF Core" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "//连接建立后,执行环境中就有了相关的类:DBContext等\n", + "DemoEFContext context = new DemoEFContext();\n", + "var t = context.Tests.ToList();\n", + "display(t);\n", + "\n", + "FormattableString fs = $\"select * from Test;\";\n", + "var c = context.Database.ExecuteSql(fs);\n", + "display(c);" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [ + "c#", + "C#" + ], + "languageName": "C#", + "name": "csharp" + }, + { + "aliases": [], + "languageName": "SQL", + "name": "sql" + }, + { + "aliases": [ + "frontend" + ], + "languageName": null, + "name": "vscode" + }, + { + "aliases": [], + "languageName": null, + "name": ".NET" + }, + { + "aliases": [ + "f#", + "F#" + ], + "languageName": "F#", + "name": "fsharp" + }, + { + "aliases": [], + "languageName": "HTML", + "name": "html" + }, + { + "aliases": [], + "languageName": "KQL", + "name": "kql" + }, + { + "aliases": [], + "languageName": "Mermaid", + "name": "mermaid" + }, + { + "aliases": [ + "powershell" + ], + "languageName": "PowerShell", + "name": "pwsh" + }, + { + "aliases": [], + "name": "value" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Docs/Jupyter笔记.2.1.原生线程.ipynb b/Docs/Jupyter笔记.2.1.原生线程.ipynb new file mode 100644 index 0000000..eb964fc --- /dev/null +++ b/Docs/Jupyter笔记.2.1.原生线程.ipynb @@ -0,0 +1,187 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "原生线程\n", + "============================== " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "由操作系统管理的线程称为原生线程,或系统线程。" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 概述" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 上下文切换" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 线程调度" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 栈空间" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [ + "c#", + "C#" + ], + "languageName": "C#", + "name": "csharp" + }, + { + "aliases": [ + "frontend" + ], + "languageName": null, + "name": "vscode" + }, + { + "aliases": [ + "powershell" + ], + "languageName": "PowerShell", + "name": "pwsh" + }, + { + "aliases": [], + "languageName": null, + "name": ".NET" + }, + { + "aliases": [ + "f#", + "F#" + ], + "languageName": "F#", + "name": "fsharp" + }, + { + "aliases": [], + "languageName": "HTML", + "name": "html" + }, + { + "aliases": [], + "languageName": "KQL", + "name": "kql" + }, + { + "aliases": [], + "languageName": "Mermaid", + "name": "mermaid" + }, + { + "aliases": [], + "languageName": "SQL", + "name": "sql" + }, + { + "aliases": [], + "languageName": null, + "name": "value" + }, + { + "aliases": [ + "js" + ], + "languageName": "JavaScript", + "name": "javascript" + }, + { + "aliases": [], + "name": "webview" + }, + { + "aliases": [], + "languageName": "T-SQL", + "name": "sql-Demo" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Docs/Jupyter笔记.2.2.托管线程.ipynb b/Docs/Jupyter笔记.2.2.托管线程.ipynb new file mode 100644 index 0000000..5d028e5 --- /dev/null +++ b/Docs/Jupyter笔记.2.2.托管线程.ipynb @@ -0,0 +1,1018 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "托管线程(Thread) 使用\n", + "============================== " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "学习 Thread,执行各种 Thread 操作。
\n", + "特别注意:NoteBook 本身的运行线程是后台线程,不会等待由其创建的线程执行结束。与控制台等应用有区别。" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 执行环境" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "

.NET Interactive

© 2020 Microsoft Corporation

Version: 1.0.415202+b72e199d0d854bd532a8103ce626a5aab4a71c07

Library version: 1.0.0-beta.23152.2+b72e199d0d854bd532a8103ce626a5aab4a71c07

Build date: 2023-03-08T16:15:05.1062967Z

https://github.com/dotnet/interactive

" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#!about" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 全局设置,语言设置、Nuget包引用、空间引用等" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "//全局设置\n", + "#!csharp\n", + "using System.Threading;\n", + "using System.Threading.Channels;\n", + "using System.Threading.Tasks;\n", + "\n", + "//全局变量\n", + "var noteBookThreadDesc = \"NoteBook线程\";\n", + "\n", + "//全局方法\n", + "//显示线程信息\n", + "public void ShowThreadInfo(Thread showThread=null, string describe = null)\n", + "{\n", + " if(showThread == null)\n", + " {\n", + " showThread = Thread.CurrentThread;\n", + " }\n", + "\n", + " if(string.IsNullOrWhiteSpace(describe))\n", + " {\n", + " describe = showThread.Name == null ? \"无名\" : showThread.Name;\n", + " }\n", + "\n", + " Console.WriteLine($\"{describe}线程ID:{showThread.ManagedThreadId} \");\n", + " Console.WriteLine($\"{describe}线程名:{showThread.Name} \");\n", + " Console.WriteLine($\"{describe}线程状态:{showThread.ThreadState} \");\n", + " Console.WriteLine($\"{describe}线程模式:{showThread.GetApartmentState()} \");\n", + " Console.WriteLine($\"{describe}激活:{(showThread.IsAlive ? \"活动\" : \"非活动\")} \");\n", + " Console.WriteLine($\"{describe}线程池线程:{(showThread.IsThreadPoolThread ? \"是的\" : \"否\")} \");\n", + " Console.WriteLine($\"{describe}后台线:{(showThread.IsBackground ? \"是的\" : \"不是\")} \");\n", + " Console.WriteLine($\"{describe}区域:{showThread.CurrentCulture}\");\n", + " Console.WriteLine($\"{describe}UI区域:{showThread.CurrentUICulture}\");\n", + " Console.WriteLine($\"{describe}优先级:{showThread.Priority}\");\n", + "}\n", + "\n", + "//显示线程状态\n", + "public void ShowThreadState(Thread showThread=null, string describe = null)\n", + "{\n", + " if(showThread == null)\n", + " {\n", + " showThread = Thread.CurrentThread;\n", + " }\n", + "\n", + " if(string.IsNullOrWhiteSpace(describe))\n", + " {\n", + " describe = showThread.Name == null ? \"无名\" : showThread.Name;\n", + " }\n", + " Console.WriteLine($\"{describe}线程状态:{showThread.ThreadState} \");\n", + "}" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 显示 Jupter Notebook (Kernel) 运行线程信息\n", + "注意:NoteBook 本身的运行线程是后台线程,不会等待由其创建的线程执行结束,这点与控制台等应用有区别。" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NoteBook线程ID:6 \n", + "NoteBook线程名:.NET ThreadPool Worker \n", + "NoteBook线程状态:Background \n", + "NoteBook线程模式:MTA \n", + "NoteBook激活:活动 \n", + "NoteBook线程池线程:是的 \n", + "NoteBook后台线:是的 \n", + "NoteBook区域:zh-CN\n", + "NoteBookUI区域:zh-CN\n", + "NoteBook优先级:Normal\n" + ] + } + ], + "source": [ + "ShowThreadInfo(null, \"NoteBook\");" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "## 使用托管线程\n", + "\n", + "注意:NoteBook 本身的运行线程是后台线程,不会等待由其创建的线程执行结束,这点与控制台等应用有区别。 " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "### 启动新线程:无参" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "ename": "Error", + "evalue": "(14,25): error CS0103: 当前上下文中不存在名称“desc”", + "output_type": "error", + "traceback": [ + "(14,25): error CS0103: 当前上下文中不存在名称“desc”" + ] + } + ], + "source": [ + "ThreadStart start = ()=>\n", + "{\n", + " Console.WriteLine($\"线程:{Thread.CurrentThread.Name},已经执行!\");\n", + "};\n", + "\n", + "var t = new Thread(start)\n", + "{\n", + " Name = \"新线程\"\n", + "};\n", + "t.Start();\n", + "//如果不join,新创建的线程,可能还没来得及执行,就随着Notebook线程的结束而结束了。\n", + "t.Join();\n", + "\n", + "Console.WriteLine($\"线程:{desc}, 执行结束!\");\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "### 启动新线程:有参" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "线程:新有参数线程,参数为 我是参数!\n", + "线程:新有参数线程,已经执行!\n", + "线程:NoteBook线程, 执行结束!\n" + ] + } + ], + "source": [ + "ParameterizedThreadStart pStart = para=>\n", + "{\n", + " Console.WriteLine($\"线程:{Thread.CurrentThread.Name},参数为 {para}!\");\n", + " Console.WriteLine($\"线程:{Thread.CurrentThread.Name},已经执行!\");\n", + "};\n", + "\n", + "var thread_para = new Thread(pStart)\n", + "{\n", + " Name=\"新有参数线程\"\n", + "};\n", + "\n", + "thread_para.Start(\"我是参数\");\n", + "thread_para.Join();\n", + "\n", + "Console.WriteLine($\"线程:{noteBookThreadDesc}, 执行结束!\");" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "### 等待线程完成" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "主线程,开始执行!\n", + "等待新线程执行完成...\n", + "新线程开始执行!\n", + "新线程执行完成!\n", + "主线程执行结束!\n" + ] + } + ], + "source": [ + "Console.WriteLine(\"主线程,开始执行!\");\n", + "\n", + "var thread_join = new Thread(()=>\n", + "{\n", + " Console.WriteLine(\"新线程开始执行!\");\n", + " Thread.Sleep(200);\n", + " Console.WriteLine(\"新线程执行完成!\");\n", + "});\n", + "\n", + "thread_join.Start();\n", + "\n", + "Console.WriteLine(\"等待新线程执行完成...\");\n", + "thread_join.Join();\n", + "\n", + "Console.WriteLine(\"主线程执行结束!\");" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "### 前台线与后台线程" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "程序启动的线程一般称为主线程或UI线程,大部分为前台线程;只有单元测试和Notebook等为后台线程。" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "主线程开始,为后台线程\n", + "新线程开始,为前台线程\n", + "新线程执行完成!\n", + "主线程结束\n" + ] + } + ], + "source": [ + "//主线程\n", + "Console.WriteLine($\"主线程开始,为{(Thread.CurrentThread.IsBackground ? \"后台\" : \"前台\")}线程\");\n", + "\n", + "var thread_isbackground = new Thread(()=>\n", + "{\n", + " Console.WriteLine($\"新线程开始,为{(Thread.CurrentThread.IsBackground ? \"后台\" : \"前台\")}线程\");\n", + " Thread.Sleep(1000);\n", + " Console.WriteLine($\"新线程执行完成!\");\n", + "});\n", + "thread_isbackground.IsBackground = false;\n", + "\n", + "thread_isbackground.Start();\n", + "thread_isbackground.Join();\n", + "\n", + "Console.WriteLine($\"主线程结束\");\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "### 线程中断与恢复" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + ".Net Core 平台不支持线程 Abort() 和 Resume()方法,推荐使用其它方法" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "主线程开始,为后台线程\n", + "新线程开始,为前台线程\n", + "中止新线程异常:Thread abort is not supported on this platform.\n", + "恢复新线程异常:Thread suspend is not supported on this platform.\n", + "新线程完成!\n", + "主线程结束\n" + ] + } + ], + "source": [ + "//主线程\n", + "Console.WriteLine($\"主线程开始,为{(Thread.CurrentThread.IsBackground ? \"后台\" : \"前台\")}线程\");\n", + "\n", + "var thread_abort = new Thread(()=>\n", + "{\n", + " Console.WriteLine($\"新线程开始,为{(Thread.CurrentThread.IsBackground ? \"后台\" : \"前台\")}线程\");\n", + " Thread.Sleep(500);\n", + " Console.WriteLine($\"新线程完成!\");\n", + "});\n", + "thread_abort.Start();\n", + "\n", + "Thread.Sleep(100);\n", + "//Abort在.net core平台不支持,会抛出异常\n", + "try\n", + "{\n", + " thread_abort.Abort();\n", + "}\n", + "//处理异常后,继续执行\n", + "catch(Exception e)\n", + "{\n", + " Console.WriteLine(\"中止新线程异常:\" + e.Message);\n", + "}\n", + "//Resume 在.net core平台不支持,会抛出异常\n", + "try\n", + "{\n", + " thread_abort.Resume();\n", + "}\n", + "//处理异常后,继续执行\n", + "catch(Exception e)\n", + "{\n", + " Console.WriteLine(\"恢复新线程异常:\" + e.Message);\n", + "}\n", + "\n", + "//等待新线程执行完成\n", + "thread_abort.Join();\n", + "\n", + "Console.WriteLine($\"主线程结束\");" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "### 线程状态及转换" + ] + }, + { + "attachments": { + "LifeCycle.png": { + "image/png": "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" + } + }, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "线程从创建到执行到结束,要经过很多状态。也就是线程的生命周期。 \n", + "![线程生命周期](attachment:LifeCycle.png)]" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "#### 线程各种状态说明" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running\n", + "StopRequested\n", + "SuspendRequested\n", + "Background\n", + "Unstarted\n", + "Stopped\n", + "WaitSleepJoin\n", + "Suspended\n", + "AbortRequested\n", + "Aborted\n" + ] + } + ], + "source": [ + "//线程各状态与说明\n", + "[Flags]\n", + "public enum ThreadState\n", + "{\n", + " // 运行中:线程已启动但尚未停止\n", + " Running = 0,\n", + "\n", + " // 正在请求线程停止,这种仅在内部使用\n", + " StopRequested = 1,\n", + "\n", + " // 正在请求线程挂起\n", + " SuspendRequested = 2,\n", + "\n", + " // 该线程作为后台线程执行,而不是前台线程。此状态通过设置 System.Thread.Thread.IsBackground 属性来控制\n", + " Background = 4,\n", + "\n", + " // 启动前:尚未在线程上调用System.Thread.Thread.Start方法\n", + " Unstarted = 8,\n", + "\n", + " // 线程已停止\n", + " Stopped = 16,\n", + "\n", + " // 线程被阻塞状态,可能的原因\n", + " // * 线程休眠:调用了 Thread.Sleep() 方法\n", + " // * 线程等待:调用了 Tthread.Join() 方法\n", + " // * 请求锁定:通过调用 Monitor.Enter()方法 或 Monitor.Wait() 方法\n", + " // * 等待线程同步对象(例如:System.Thread.ManualResetEvent)的结果\n", + " // * 其它内部机制\n", + " WaitSleepJoin = 32,\n", + "\n", + " // 线程已挂起\n", + " Suspended = 64,\n", + "\n", + " // 已在线程上调用 Abort 方法,但线程尚未收到抛出的挂起异常时间的状态\n", + " AbortRequested = 128,\n", + "\n", + " // 线程状态包括AbortRequested,并且线程现在已停止,但其状态尚未更改为Stop\n", + " Aborted = 256\n", + "}\n", + "\n", + "foreach(var a in System.Enum.GetNames())\n", + "{\n", + " Console.WriteLine(a);\n", + "}" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "#### 普通执行流程" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "未开始[Unstarted] => 运行中[Running] => 阻塞状态[WaitSleepJoin] => 恢复执行[Running] => 停止[Stopped]" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "主线程开始!\n", + "新线程: 未启动时状态为 Unstarted\n", + "新线程: 启动后的状态为 Running\n", + "新线程状态:Running => WaitSleepJoin\n", + "新线程状态:WaitSleepJoin => Running\n", + "新线程:Join后的状态为 Stopped\n", + "主线程结束!\n" + ] + } + ], + "source": [ + "//主线程\n", + "Console.WriteLine($\"主线程开始!\");\n", + "\n", + "var stateThread_1 = new Thread(()=>\n", + "{\n", + " //Console.WriteLine($\"新线程开始,状态为{Thread.CurrentThread.ThreadState}\");\n", + " Thread.Sleep(500);\n", + "\n", + " for(int i=0;i<1000000;i++)\n", + " {\n", + " var result = Math.BigMul(7897987,456464565)+Math.Pow(4646.2343,4646.33);\n", + " }\n", + " //Console.WriteLine($\"新线程完成!\");\n", + "});\n", + "\n", + "//未启动线程\n", + "Console.WriteLine($\"新线程: 未启动时状态为 {stateThread_1.ThreadState}\");\n", + "\n", + "//启动线程\n", + "stateThread_1.Start();\n", + "Console.WriteLine($\"新线程: 启动后的状态为 {stateThread_1.ThreadState}\");\n", + "\n", + "//主线程循环检测新线程状态\n", + "var preState1 = stateThread_1.ThreadState;\n", + "while(true)\n", + "{\n", + " if(!stateThread_1.IsAlive) break;\n", + " if(preState1 != stateThread_1.ThreadState)\n", + " {\n", + " Console.WriteLine($\"新线程状态:{preState1} => {stateThread_1.ThreadState}\");\n", + " preState1 = stateThread_1.ThreadState;\n", + " }\n", + "}\n", + "//主线程等待新线程结束\n", + "if(Thread.CurrentThread.IsBackground)\n", + "{\n", + " stateThread_1.Join();\n", + "}\n", + "\n", + "\n", + "//执行完成状态\n", + "Console.WriteLine($\"新线程:Join后的状态为 {stateThread_1.ThreadState}\");\n", + "\n", + "Console.WriteLine($\"主线程结束!\");" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "#### 后台线程普通流程" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "未开始[Unstarted] => 后台运行中[Background] => 后台与阻塞状态[Background,WaitSleepJoin] => 恢复后台执行[Background] => 停止[Stopped]" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "主线程开始!\n", + "新线程: 未启动时状态为 Background, Unstarted\n", + "新线程: 启动后的状态为 Background\n", + "新线程状态:Background => Background, WaitSleepJoin\n", + "新线程状态:Background, WaitSleepJoin => Background\n", + "新线程:Join后的状态为 Stopped\n", + "主线程结束!\n" + ] + } + ], + "source": [ + "//主线程\n", + "Console.WriteLine($\"主线程开始!\");\n", + "\n", + "var stateThread_2 = new Thread(() =>\n", + "{\n", + " Thread.Sleep(500);\n", + "\n", + " for (int i = 0; i < 1000000; i++)\n", + " {\n", + " var result = Math.BigMul(7897987, 456464565) + Math.Pow(4646.2343, 4646.33);\n", + " }\n", + "});\n", + "stateThread_2.IsBackground=true;\n", + "\n", + "//未启动线程\n", + "Console.WriteLine($\"新线程: 未启动时状态为 {stateThread_2.ThreadState}\");\n", + "\n", + "//启动线程\n", + "stateThread_2.Start();\n", + "Console.WriteLine($\"新线程: 启动后的状态为 {stateThread_2.ThreadState}\");\n", + "\n", + "//主线程循环检测新线程状态\n", + "var preState1 = stateThread_2.ThreadState;\n", + "while (true)\n", + "{\n", + " if (!stateThread_2.IsAlive) break;\n", + " if (preState1 != stateThread_2.ThreadState)\n", + " {\n", + " Console.WriteLine($\"新线程状态:{preState1} => {stateThread_2.ThreadState}\");\n", + " preState1 = stateThread_2.ThreadState;\n", + " }\n", + "}\n", + "//主线程等待新线程结束\n", + "stateThread_2.Join();\n", + "\n", + "//执行完成状态\n", + "Console.WriteLine($\"新线程:Join后的状态为 {stateThread_2.ThreadState}\");\n", + "\n", + "Console.WriteLine($\"主线程结束!\");" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "### 是否线程池线程" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "Thread 类管理的线程,均为非线程池线程。 \n", + "注意:Notebook执行线程是线程池线程。" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "主线程开始,为线程池线程\n", + "主线程结束!\n", + "新线程开始,为非线程池线程\n", + "新线程完成!\n" + ] + } + ], + "source": [ + "//主线程\n", + "Console.WriteLine($\"主线程开始,为{(Thread.CurrentThread.IsThreadPoolThread ? \"线程池\" : \"非线程池\")}线程\");\n", + "\n", + "var thread_isPoolThread = new Thread(()=>\n", + "{\n", + " Console.WriteLine($\"新线程开始,为{(Thread.CurrentThread.IsThreadPoolThread ? \"线程池\" : \"非线程池\")}线程\");\n", + " Console.WriteLine($\"新线程完成!\");\n", + "});\n", + "thread_isPoolThread.Start();\n", + "if(thread_isPoolThread.IsBackground)\n", + "{\n", + " thread_isPoolThread.Join();\n", + "}\n", + "\n", + "Console.WriteLine($\"主线程结束!\");" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [ + "c#", + "C#" + ], + "languageName": "C#", + "name": "csharp" + }, + { + "aliases": [ + "frontend" + ], + "languageName": null, + "name": "vscode" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Docs/Jupter笔记.002.线程.ipynb b/Docs/Jupyter笔记.2.3.抢占与合作模式.ipynb similarity index 52% rename from Docs/Jupter笔记.002.线程.ipynb rename to Docs/Jupyter笔记.2.3.抢占与合作模式.ipynb index 2f8f977..4620d88 100644 --- a/Docs/Jupter笔记.002.线程.ipynb +++ b/Docs/Jupyter笔记.2.3.抢占与合作模式.ipynb @@ -12,10 +12,8 @@ } }, "source": [ - "Thread 使用\n", - "==============================\n", - "学习 Thread,执行各种 Thread 操作。\n", - "特别注意:NoteBook 本身的运行线程是后台线程,不会等待由其创建的线程执行结束。与控制台等应用有区别。 " + "抢占模式与合作模式\n", + "==============================" ] }, { @@ -30,30 +28,8 @@ } }, "source": [ - "> 全局设置,语言设置、Nuget包引用、空间引用等" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "//全局设置\n", - "#!csharp\n", - "using System.Threading;\n", - "using System.Threading.Channels;\n", - "using System.Threading.Tasks;" + "学习 Thread,执行各种 Thread 操作。 \n", + "特别注意:NoteBook 本身的运行线程是后台线程,不会等待由其创建的线程执行结束。与控制台等应用有区别。 " ] }, { @@ -68,12 +44,12 @@ } }, "source": [ - "> 创建托管线程,注意:NoteBook 本身的运行线程是后台线程,不会等待由其创建的线程执行结束,这点与控制台等应用有区别。 " + "## 全局设置,语言设置、Nuget包引用、空间引用等" ] }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 1, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -85,66 +61,16 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "NoteBook线程,线程ID:6 \n", - "NoteBook线程,线程名:.NET ThreadPool Worker \n", - "NoteBook线程,线程池线程:是的 \n", - "NoteBook线程,后台线:是的 \n" - ] - } - ], - "source": [ - "//显示 NoteBook 执行线程信息\n", - "var desc = \"NoteBook线程,\";\n", - "Console.WriteLine($\"{desc}线程ID:{Thread.CurrentThread.ManagedThreadId} \");\n", - "Console.WriteLine($\"{desc}线程名:{Thread.CurrentThread.Name} \");\n", - "Console.WriteLine($\"{desc}线程池线程:{(Thread.CurrentThread.IsThreadPoolThread ? \"是的\" : \"否\")} \");\n", - "Console.WriteLine($\"{desc}后台线:{(Thread.CurrentThread.IsBackground ? \"是的\" : \"不是\")} \");" - ] - }, - { - "cell_type": "code", - "execution_count": 60, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "线程:新线程,已经执行!\n", - "线程:NoteBook线程,, 执行结束!\n" - ] - } - ], + "outputs": [], "source": [ - "ThreadStart start = ()=>\n", - "{\n", - " Console.WriteLine($\"线程:{Thread.CurrentThread.Name},已经执行!\");\n", - "};\n", - "\n", - "var t = new Thread(start)\n", - "{\n", - " Name=\"新线程\"\n", - "};\n", - "t.Start();\n", - "//如果不join,新创建的线程,可能还没来得及执行,就随着Notebook线程的结束而结束了。\n", - "t.Join();\n", + "//全局设置\n", + "#!csharp\n", + "using System.Threading;\n", + "using System.Threading.Channels;\n", + "using System.Threading.Tasks;\n", "\n", - "Console.WriteLine($\"线程:{desc}, 执行结束!\");\n" + "//全局变量\n", + "var noteBookThreadDesc = \"NoteBook线程\";" ] } ], @@ -182,6 +108,7 @@ }, { "aliases": [], + "languageName": null, "name": ".NET" }, { @@ -214,6 +141,7 @@ }, { "aliases": [], + "languageName": null, "name": "value" }, { diff --git a/Docs/assets/images/LifeCycle.png b/Docs/assets/images/LifeCycle.png new file mode 100644 index 0000000..07027d4 Binary files /dev/null and b/Docs/assets/images/LifeCycle.png differ diff --git a/Docs/并发与并行.md b/Docs/并发与并行.md new file mode 100644 index 0000000..95c5682 --- /dev/null +++ b/Docs/并发与并行.md @@ -0,0 +1,21 @@ +# **并行与并发** + +# 概念: + +**并发**:同时发生(申请):申请者(应用)将多个任务`同时或同一时间间隔`向`单一执行者(`CPU)申请执行;执行者同时接收或同时存在多外执行任务,`交替(非同时)执行`,因执行的非常快,`在申请方看来,是多个申请同时得到执行`。 + +**并行**:同时执行:申请者(应用)将多个任务`同一时刻`向`多个执行者(`CPU)申请执行;多个执行者`同时接收并同时执行`。 + +## 区别: + ++ 对象不同:并发针对单一执行者(CPU),并行针对多个执行者(CPU) + ++ 时间不同:并发指同一时间间隔,申请者宏观上看任务是同时得到处理(因为执者执行的非常快,交替执行的时间片很小),执行者微观上是交替执行(一个执行者,同一时刻只能执行一个任务);并行指同一时刻,多个执行者(CPU)同时处理多个任务(其中每个处理者处理一个任务)。 + ++ 含义不同:并发同一执行者,宏观上同时处理多个任务;并行是多个执行者,微观上同一时刻,执行多个任务。 + +## 联系: + ++ 单核 CPU:只能并发不能并行;提高响应能力。 + ++ 多核 CPU:多核上可以并行,提高吞吐量;同时在每个核心上可能并发,提高响应能力。