diff --git a/Docs/Base.ipynb b/Docs/Base.ipynb new file mode 100644 index 0000000..d357002 --- /dev/null +++ b/Docs/Base.ipynb @@ -0,0 +1,149 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0be6f6cc", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "ename": "Error", + "evalue": "(66,24): error CS0234: 命名空间“System.ComponentModel”中不存在类型或命名空间名“DataAnnotations”(是否缺少程序集引用?)", + "output_type": "error", + "traceback": [ + "(66,24): error CS0234: 命名空间“System.ComponentModel”中不存在类型或命名空间名“DataAnnotations”(是否缺少程序集引用?)" + ] + } + ], + "source": [ + "#r \"nuget:Microsoft.Extensions.DependencyInjection\"\n", + "#r \"nuget:Microsoft.Extensions.Options\"\n", + "#r \"nuget:Microsoft.Extensions.Options.DataAnnotations\"\n", + "#r \"nuget:Microsoft.Extensions.Configuration\"\n", + "#r \"nuget:Microsoft.Extensions.Configuration.Binder\"\n", + "#r \"nuget:Microsoft.Extensions.Configuration.ini\"\n", + "#r \"nuget:Microsoft.Extensions.Configuration.xml\"\n", + "#r \"nuget:Microsoft.Extensions.Configuration.json\"\n", + "#r \"nuget:Microsoft.Extensions.Configuration.KeyPerFile\"\n", + "#r \"nuget:Microsoft.Extensions.Configuration.UserSecrets\"\n", + "#r \"nuget:Microsoft.Extensions.Configuration.CommandLine\"\n", + "#r \"nuget:Microsoft.Extensions.Configuration.EnvironmentVariables\"\n", + "#r \"nuget:Microsoft.Extensions.Options.ConfigurationExtensions\"\n", + "#r \"nuget:Microsoft.Extensions.Logging\"\n", + "#r \"nuget:Microsoft.Extensions.Logging.Console\"\n", + "#r \"nuget:Microsoft.Extensions.Logging.Debug\"\n", + "#r \"nuget:Microsoft.Extensions.Logging.EventSource\"\n", + "#r \"nuget:Microsoft.Extensions.Logging.Configuration\"\n", + "\n", + "global using Microsoft.Extensions.DependencyInjection;\n", + "global using Microsoft.Extensions.Configuration;\n", + "global using Microsoft.Extensions.Configuration.Ini;\n", + "global using Microsoft.Extensions.Configuration.Xml;\n", + "global using Microsoft.Extensions.Configuration.Memory;\n", + "global using Microsoft.Extensions.Configuration.Json;\n", + "global using Microsoft.Extensions.Configuration.CommandLine;\n", + "global using Microsoft.Extensions.Configuration.EnvironmentVariables;\n", + "global using Microsoft.Extensions.Options;\n", + "global using Microsoft.Extensions.Logging;\n", + "global using Microsoft.Extensions.Logging.Debug;\n", + "global using Microsoft.Extensions.Logging.Console;\n", + "global using Microsoft.Extensions.Logging.EventSource;\n", + "global using Microsoft.Extensions.Logging.Configuration;\n", + "\n", + "//环境变量\n", + "//Environment.SetEnvironmentVariable(\"Database:PSQL\", \"Host=localhost;Port=5432;Username=postgres;Password=psql-461400;Database=Study;\", EnvironmentVariableTarget.Process);\n", + "\n", + "//配置文件\n", + "IConfigurationBuilder configBuilder = new ConfigurationBuilder();\n", + "configBuilder\n", + " .SetBasePath(Environment.CurrentDirectory)\n", + " .AddJsonFile(\"config.json\",false,true)\n", + " .AddEnvironmentVariables()\n", + " .AddUserSecrets(\"PolyglotNotebooksStudy\",true)\n", + " .AddCommandLine(new string[]{})\n", + ";\n", + "\n", + "public IConfiguration DataBaseConfig = configBuilder.Build();\n", + "\n", + "//DI\n", + "ServiceCollection Services = new ServiceCollection();\n", + "Services\n", + " .AddSingleton(DataBaseConfig)\n", + " .AddLogging(setup =>\n", + " {\n", + " setup.AddConfiguration();\n", + " setup.AddDebug();\n", + " setup.AddConsole();\n", + " })\n", + " ;\n", + "public ServiceProvider SharedContainer = Services.BuildServiceProvider();\n", + "\n", + "public class DbConnectionString\n", + "{\n", + " public string MsSqlConnectionString {get;set;}\n", + " public string MySQLConnectionString {get;set;}\n", + " public string PSQLConnectionString {get;set;}\n", + " public string SQLiteConnectionString {get;set;}\n", + " public string DuckDBConnectionString {get;set;}\n", + "}\n", + "\n", + "///\n", + "/// 数据库连接字符串\n", + "///\n", + "public DbConnectionString SharedDbConnect = new DbConnectionString()\n", + "{\n", + " MsSqlConnectionString = DataBaseConfig.GetValue(\"Database:SQLServer\"),\n", + " MySQLConnectionString = DataBaseConfig.GetValue(\"Database:MySQL\"),\n", + " PSQLConnectionString = DataBaseConfig.GetValue(\"Database:PSQL\"),\n", + " SQLiteConnectionString = DataBaseConfig.GetValue(\"Database:SQLite\"),\n", + " DuckDBConnectionString = DataBaseConfig.GetValue(\"Database:DuckDB\"),\n", + "};\n", + "\n", + "//SharedDbConnect.Display();\n", + "\n", + "public class Student\n", + "{\n", + " public int Id {get;set;}\n", + "\n", + " public string Name {get;set;}\n", + "\n", + " public int Age {get;set;}\n", + "}" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "languageName": "csharp", + "name": "csharp" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Docs/assets/database/SQL Server.Study.bak b/Docs/assets/database/SQL Server.Study.bak new file mode 100644 index 0000000..aa088ba Binary files /dev/null and b/Docs/assets/database/SQL Server.Study.bak differ diff --git a/Docs/assets/database/SQLServer2019.Study.SQLScript.sql b/Docs/assets/database/SQLServer2019.Study.SQLScript.sql new file mode 100644 index 0000000..5c2b30b --- /dev/null +++ b/Docs/assets/database/SQLServer2019.Study.SQLScript.sql @@ -0,0 +1,1124 @@ +--ʹStudyݿ(ֶǰ) +USE [Study] +GO + +/****** Object: Table [dbo].[Student] Script Date: 2025/4/14 10:26:46 ******/ +SET ANSI_NULLS ON +GO + +SET QUOTED_IDENTIFIER ON +GO +-- +CREATE TABLE [dbo].[Student]( + [Id] [INT] IDENTITY(1,1) NOT NULL, + [Name] [NVARCHAR](50) NULL, + [Age] [INT] NULL, + CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED +( + [Id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] +) ON [PRIMARY] +GO +-- +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',74), + (N'Τ',3), + (N'Ҧ',27), + (N'',18), + (N'',5), + (N'ֽܺ',73), + (N'',60), + (N'',23), + (N'Ӣ',6), + (N'Ԋ',82); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ӣ',87), + (N'',12), + (N'',65), + (N'Զ',14), + (N'Զ',46), + (N'',12), + (N'',21), + (N'ల',2), + (N'',6), + (N'¬',63); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'׽ܺ',57), + (N'',39), + (N'',73), + (N'ʷ',62), + (N'',81), + (N'Ű',86), + (N'Զ',24), + (N'ʯԊ',89), + (N'ܺ',92), + (N'',62); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'ƽܺ',67), + (N'',21), + (N'',99), + (N'½ܺ',58), + (N'',84), + (N'ϼ',39), + (N'',3), + (N'Զ',77), + (N'ʯ',52), + (N'Ԋ',82); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',80), + (N'',61), + (N'ܺ',45), + (N'',62), + (N'',98), + (N'',3), + (N'',10), + (N'',28), + (N'',57), + (N'',73); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ԭ',49), + (N'',9), + (N'ΤԶ',4), + (N'Ī',1), + (N'',96), + (N'',36), + (N'Ӣ',11), + (N'',58), + (N'Ԋ',94), + (N'',23); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ԋ',74), + (N'',95), + (N'',8), + (N'Ӣ',53), + (N'',99), + (N'',92), + (N'',16), + (N'Ӣ',90), + (N'',46), + (N'Ӣ',67); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Զ',4), + (N'',37), + (N'',5), + (N'Ҷ',53), + (N'',6), + (N'',95), + (N'',93), + (N'',78), + (N'ܺ',72), + (N'Ӣ',50); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',63), + (N'',47), + (N'ư',5), + (N'ڰ',64), + (N'',85), + (N'',15), + (N'Զ',84), + (N'',49), + (N'Ԋ',81), + (N'Ԋ',5); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'װ',60), + (N'νܺ',63), + (N'Զ',64), + (N'Զ',50), + (N'׽ܺ',34), + (N'',90), + (N'Ҷ',11), + (N'',91), + (N'',95), + (N'ʷ',49); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Τ',59), + (N'',75), + (N'ల',50), + (N'Զ',72), + (N'Ԋ',65), + (N'',21), + (N'Ƽ',39), + (N'ëԊ',79), + (N'',54), + (N'',16); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ԭ',52), + (N'',20), + (N'',39), + (N'',3), + (N'',50), + (N'',83), + (N'Ԋ',21), + (N'Զ',59), + (N'',11), + (N'',54); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',62), + (N'',21), + (N'',18), + (N'Ԋ',8), + (N'',43), + (N'νܺ',7), + (N'½',42), + (N'',26), + (N'Ԋ',50), + (N'',74); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',35), + (N'',32), + (N'Ҷ',42), + (N'ʷӢ',38), + (N'',11), + (N'Ԋ',32), + (N'',31), + (N'½ܺ',91), + (N'',12), + (N'',80); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',81), + (N'Ԋ',65), + (N'Ԋ',93), + (N'Ӣ',48), + (N'',83), + (N'½',81), + (N'',74), + (N'',5), + (N'',63), + (N'',80); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'֣',48), + (N'½Ԋ',86), + (N'',68), + (N'',67), + (N'',35), + (N'Ԋ',12), + (N'Ӣ',16), + (N'ʯԊ',12), + (N'',83), + (N'',51); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'ܺ',29), + (N'Ԋ',12), + (N'Զ',72), + (N'',76), + (N'',18), + (N'װ',60), + (N'',96), + (N'½',94), + (N'',74), + (N'Ԋ',21); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'ܽܺ',20), + (N'',61), + (N'',67), + (N'',38), + (N'ĪӢ',74), + (N'',2), + (N'½',43), + (N'',27), + (N'',31), + (N'',58); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',8), + (N'',50), + (N'ëܺ',42), + (N'Ӣ',30), + (N'',67), + (N'',94), + (N'',23), + (N'',53), + (N'ë',78), + (N'',43); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',71), + (N'',31), + (N'Ӣ',78), + (N'',5), + (N'',93), + (N'',53), + (N'',6), + (N'',87), + (N'Ӣ',96), + (N'',46); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',54), + (N'',1), + (N'',30), + (N'',6), + (N'̷',49), + (N'¬',28), + (N'',56), + (N'',65), + (N'Ҧ',44), + (N'',68); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'ּ',16), + (N'',59), + (N'',7), + (N'̷',48), + (N'',90), + (N'',62), + (N'',14), + (N'',48), + (N'',9), + (N'',74); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ӣ',39), + (N'',81), + (N'',34), + (N'',45), + (N'',50), + (N'Ԋ',23), + (N'ܺ',70), + (N'ʯܺ',26), + (N'',34), + (N'',84); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',29), + (N'',99), + (N'',10), + (N'Ӣ',94), + (N'Ӣ',39), + (N'Ԋ',28), + (N'۰',4), + (N'Τ',14), + (N'',94), + (N'',5); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',7), + (N'Ӣ',37), + (N'',27), + (N'л',58), + (N'л',58), + (N'ǮӢ',8), + (N'ܺ',56), + (N'Զ',60), + (N'',39), + (N'',16); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',85), + (N'ּ',18), + (N'',83), + (N'',60), + (N'Ӣ',92), + (N'',45), + (N'лԊ',54), + (N'',89), + (N'ְ',80), + (N'',86); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',59), + (N'',52), + (N'Զ',22), + (N'',14), + (N'',40), + (N'',61), + (N'',5), + (N'',59), + (N'',80), + (N'μ',82); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'̷',40), + (N'¬',83), + (N'',30), + (N'',46), + (N'',19), + (N'Ӣ',8), + (N'İ',41), + (N'',86), + (N'',92), + (N'',63); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ӣ',19), + (N'Ҧ',12), + (N'Ӣ',64), + (N'л',95), + (N'ְ',61), + (N'Ԋ',9), + (N'',43), + (N'ܽܺ',82), + (N'ܺ',75), + (N'ʷ',8); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',74), + (N'',16), + (N'',90), + (N'Ԋ',24), + (N'',87), + (N'',10), + (N'',13), + (N'',50), + (N'ذ',87), + (N'',59); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ӣ',79), + (N'л',48), + (N'',54), + (N'',76), + (N'',99), + (N'',67), + (N'̷',91), + (N'',52), + (N'',78), + (N'ʷԶ',18); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',33), + (N'',72), + (N'',95), + (N'Ԋ',64), + (N'',74), + (N'ĪԶ',79), + (N'',84), + (N'',97), + (N'Ӣ',7), + (N'Ӣ',25); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',49), + (N'',43), + (N'',79), + (N'Ӣ',34), + (N'Ԋ',12), + (N'Ԭ',82), + (N'',75), + (N'',49), + (N'',99), + (N'',61); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',30), + (N'',66), + (N'Ҧ',62), + (N'',60), + (N'',6), + (N'',94), + (N'',83), + (N'Ӣ',99), + (N'',89), + (N'ؽܺ',6); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',63), + (N'',51), + (N'',75), + (N'',22), + (N'',40), + (N'',61), + (N'',95), + (N'˼',87), + (N'',33), + (N'',59); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',44), + (N'Զ',30), + (N'',57), + (N'ëԶ',26), + (N'',27), + (N'',90), + (N'',46), + (N'',93), + (N'',87), + (N'ܽܺ',9); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'ܺ',39), + (N'Žܺ',4), + (N'Ԋ',16), + (N'Ԋ',82), + (N'',45), + (N'ల',90), + (N'',31), + (N'',18), + (N'',87), + (N'޼',46); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',41), + (N'',35), + (N'',19), + (N'',2), + (N'',36), + (N'',94), + (N'',91), + (N'ܺ',70), + (N'ʷ',76), + (N'',3); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',8), + (N'Ԭ',99), + (N'',35), + (N'μ',52), + (N'Զ',84), + (N'Ӣ',62), + (N'ۼ',62), + (N'',91), + (N'Լ',76), + (N'',34); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',62), + (N'',90), + (N'',75), + (N'ʯ',18), + (N'',94), + (N'',33), + (N'',37), + (N'κ',48), + (N'Զ',38), + (N'',96); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',38), + (N'ëӢ',70), + (N'¬',58), + (N'',90), + (N'Ԋ',34), + (N'',89), + (N'',51), + (N'',36), + (N'',61), + (N'',2); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',22), + (N'½',47), + (N'Ԋ',99), + (N'',14), + (N'',57), + (N'',40), + (N'հ',74), + (N'',40), + (N'',63), + (N'',3); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',5), + (N'۰',60), + (N'',43), + (N'Ԋ',51), + (N'',74), + (N'',36), + (N'',46), + (N'',2), + (N'',95), + (N'Ԋ',63); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',4), + (N'',55), + (N'',2), + (N'',63), + (N'Ӣ',73), + (N'',96), + (N'',14), + (N'Ԋ',56), + (N'½',97), + (N'',20); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',78), + (N'',51), + (N'Ī',72), + (N'',97), + (N'',78), + (N'ʯ',61), + (N'ܺ',74), + (N'Ǯ',11), + (N'',8), + (N'',86); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',82), + (N'',67), + (N'',58), + (N'',33), + (N'Ӣ',63), + (N'',94), + (N'л',99), + (N'',62), + (N'',21), + (N'',71); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',84), + (N'',62), + (N'',78), + (N'ΰ',63), + (N'',14), + (N'',11), + (N'ְ',74), + (N'',43), + (N'Ӣ',44), + (N'',93); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',94), + (N'',11), + (N'ĪӢ',64), + (N'Զ',58), + (N'Զ',26), + (N'',77), + (N'¬ܺ',97), + (N'',79), + (N'',32), + (N'',59); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ҧ',36), + (N'ܺ',100), + (N'Ԋ',2), + (N'',68), + (N'',28), + (N'',69), + (N'Զ',65), + (N'Ԋ',81), + (N'Ӣ',75), + (N'޽ܺ',21); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',86), + (N'',12), + (N'Τ',97), + (N'',84), + (N'Ԋ',58), + (N'̽ܺ',92), + (N'',74), + (N'',100), + (N'ʯ',95), + (N'',27); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',82), + (N'',84), + (N'',86), + (N'',57), + (N'κ',38), + (N'',51), + (N'',89), + (N'',82), + (N'',72), + (N'Ӣ',5); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Զ',68), + (N'',81), + (N'',47), + (N'',81), + (N'Ӣ',84), + (N'ܼ',86), + (N'ܺ',68), + (N'¬',74), + (N'',81), + (N'Զ',67); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',7), + (N'',38), + (N'',44), + (N'',82), + (N'Ӱ',44), + (N'̷Ԋ',69), + (N'',55), + (N'',58), + (N'Ԋ',14), + (N'',11); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',65), + (N'̷',21), + (N'',85), + (N'½',21), + (N'ʯ',72), + (N'Ǯ',72), + (N'Ű',36), + (N'Ǯ',14), + (N'Զ',97), + (N'Ԋ',98); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ԋ',48), + (N'л',85), + (N'',36), + (N'',89), + (N'',80), + (N'',15), + (N'Ӣ',59), + (N'Ԋ',31), + (N'ܺ',94), + (N'',12); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ű',60), + (N'ּ',48), + (N'',64), + (N'',88), + (N'',29), + (N'',95), + (N'Զ',12), + (N'',73), + (N'ʷ',64), + (N'Զ',83); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'ļ',40), + (N'Զ',90), + (N'',34), + (N'¬',13), + (N'',93), + (N'ʷ',85), + (N'Ӣ',82), + (N'Ԋ',23), + (N'',8), + (N'',21); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',31), + (N'',59), + (N'',17), + (N'',79), + (N'',93), + (N'ܰ',8), + (N'',60), + (N'Ī',44), + (N'',47), + (N'',49); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',47), + (N'',17), + (N'ܺ',99), + (N'',87), + (N'',44), + (N'',32), + (N'л',89), + (N'Ӣ',72), + (N'Ԋ',22), + (N'',99); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',39), + (N'Ӣ',17), + (N'',25), + (N'Ű',31), + (N'Ǯ',65), + (N'Ԋ',50), + (N'Զ',86), + (N'',20), + (N'',45), + (N'½Զ',75); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ԋ',78), + (N'Τ',23), + (N'',75), + (N'κܺ',85), + (N'̷',14), + (N'',38), + (N'',49), + (N'',19), + (N'',64), + (N'',24); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',56), + (N'',41), + (N'',87), + (N'Ӣ',6), + (N'',98), + (N'˼',61), + (N'Ѧ',94), + (N'',45), + (N'',11), + (N'',82); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',10), + (N'Զ',5), + (N'Ǯ',17), + (N'Ӣ',25), + (N'',39), + (N'',84), + (N'',47), + (N'Զ',9), + (N'',32), + (N'',22); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',52), + (N'ܰ',87), + (N'',65), + (N'Զ',17), + (N'',69), + (N'',57), + (N'',17), + (N'Զ',63), + (N'̽ܺ',89), + (N'Ԭܺ',75); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',65), + (N'ܺ',94), + (N'',53), + (N'',52), + (N'Τ',84), + (N'',35), + (N'',6), + (N'',3), + (N'',56), + (N'¬',7); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',47), + (N'ܺ',52), + (N'ܺ',39), + (N'',27), + (N'',46), + (N'',22), + (N'',91), + (N'Ԋ',58), + (N'Ԋ',48), + (N'Ī',8); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'°',33), + (N'̷Ӣ',11), + (N'½',31), + (N'',33), + (N'',76), + (N'Ԋ',72), + (N'л',2), + (N'',75), + (N'',25), + (N'',95); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',91), + (N'',67), + (N'',36), + (N'Ѧ',11), + (N'',85), + (N'',84), + (N'ΤӢ',58), + (N'̷Զ',8), + (N'밲',83), + (N'',89); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'ް',52), + (N'¬Ԋ',4), + (N'Զ',15), + (N'',21), + (N'',36), + (N'',37), + (N'',45), + (N'ë',35), + (N'νܺ',47), + (N'',67); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ԭ',21), + (N'½',86), + (N'',3), + (N'',89), + (N'',40), + (N'',79), + (N'',63), + (N'ư',30), + (N'',24), + (N'',46); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',50), + (N'',98), + (N'',38), + (N'̼',74), + (N'ҦӢ',27), + (N'',31), + (N'½',66), + (N'ļ',50), + (N'¬',72), + (N'',66); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',75), + (N'',22), + (N'װ',90), + (N'',35), + (N'ë',68), + (N'ҦԊ',39), + (N'ΰ',85), + (N'',21), + (N'Ӣ',18), + (N'',6); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',92), + (N'',78), + (N'',7), + (N'',2), + (N'',66), + (N'',67), + (N'',47), + (N'ؽܺ',35), + (N'սܺ',11), + (N'',72); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',1), + (N'Ԋ',39), + (N'',37), + (N'',82), + (N'',25), + (N'Ī',83), + (N'Ԭܺ',31), + (N'',29), + (N'Զ',71), + (N'',14); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'ë',89), + (N'Զ',46), + (N'',98), + (N'Ԋ',84), + (N'',78), + (N'Ӣ',56), + (N'֣',48), + (N'',64), + (N'հ',77), + (N'',2); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',49), + (N'',82), + (N'',36), + (N'Զ',7), + (N'Ӣ',28), + (N'',45), + (N'',13), + (N'ΤԶ',5), + (N'',41), + (N'',5); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',38), + (N'ëܺ',35), + (N'ϼ',86), + (N'Ӣ',51), + (N'ܰ',71), + (N'',28), + (N'Ԋ',78), + (N'Ԋ',41), + (N'',58), + (N'',81); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',65), + (N'Զ',71), + (N'ּ',48), + (N'',60), + (N'Ԋ',98), + (N'',39), + (N'ܺ',31), + (N'',76), + (N'',91), + (N'',61); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'κԊ',62), + (N'ë',27), + (N'',65), + (N'',95), + (N'',4), + (N'',35), + (N'',50), + (N'',43), + (N'Զ',25), + (N'Ӣ',66); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',77), + (N'',69), + (N'',6), + (N'',45), + (N'',83), + (N'',32), + (N'',36), + (N'μ',74), + (N'Զ',70), + (N'',84); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',16), + (N'',92), + (N'',10), + (N'',46), + (N'',78), + (N'',49), + (N'Τ',82), + (N'Ԋ',41), + (N'ԬԶ',63), + (N'°',45); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',77), + (N'Ԋ',80), + (N'Զ',97), + (N'ذ',41), + (N'',6), + (N'',53), + (N'',2), + (N'',78), + (N'½',85), + (N'κ',78); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',43), + (N'',3), + (N'',19), + (N'',84), + (N'',76), + (N'Զ',80), + (N'Ԋ',20), + (N'',73), + (N'Ӣ',63), + (N'',99); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'ʷܺ',78), + (N'κܺ',78), + (N'Ԋ',74), + (N'Զ',14), + (N'ĪӢ',37), + (N'Ǯ',29), + (N'',7), + (N'',89), + (N'Ӣ',13), + (N'ʷ',22); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',69), + (N'ǮԶ',55), + (N'',18), + (N'',58), + (N'',57), + (N'',62), + (N'Ԋ',42), + (N'Զ',24), + (N'',57), + (N'',16); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',78), + (N'',70), + (N'¬',68), + (N'',46), + (N'ܺ',70), + (N'ʯ',42), + (N'',1), + (N'',26), + (N'',97), + (N'',54); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'̰',85), + (N'',85), + (N'Ԋ',17), + (N'Ǯ',97), + (N'ܺ',35), + (N'',28), + (N'ܺ',34), + (N'Զ',10), + (N'',90), + (N'',88); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ӣ',89), + (N'Ԋ',56), + (N'Ī',81), + (N'',42), + (N'Զ',58), + (N'Ԭ',42), + (N'',70), + (N'ؽܺ',65), + (N'',37), + (N'Ԋ',20); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'¬',85), + (N'',39), + (N'',8), + (N'Ӣ',23), + (N'',61), + (N'ż',58), + (N'Ӣ',35), + (N'л',18), + (N'',24), + (N'',33); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'¼',68), + (N'',64), + (N'',84), + (N'',95), + (N'',73), + (N'ǮԶ',26), + (N'Զ',38), + (N'',36), + (N'',35), + (N'',99); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',17), + (N'',41), + (N'',15), + (N'',78), + (N'',85), + (N'Τ',89), + (N'Ԋ',77), + (N'Ԋ',96), + (N'Զ',92), + (N'',99); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',20), + (N'',95), + (N'Ӣ',38), + (N'Ӣ',70), + (N'ʯ',95), + (N'',76), + (N'',36), + (N'',71), + (N'',100), + (N'',70); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',53), + (N'',42), + (N'',86), + (N'',69), + (N'',96), + (N'',12), + (N'Ӣ',41), + (N'',37), + (N'Ԭ',75), + (N'ۼ',95); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',13), + (N'',92), + (N'ܽܺ',84), + (N'',13), + (N'',30), + (N'',13), + (N'',82), + (N'',70), + (N'',50), + (N'',70); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',63), + (N'',25), + (N'',38), + (N'߽ܺ',90), + (N'',52), + (N'',24), + (N'',48), + (N'',16), + (N'',69), + (N'Զ',69); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ԋ',88), + (N'',48), + (N'',91), + (N'',66), + (N'',91), + (N'',91), + (N'',50), + (N'Ѧ',13), + (N'',82), + (N'',60); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Ԋ',92), + (N'½',35), + (N'',93), + (N'',58), + (N'Զ',19), + (N'',34), + (N'',70), + (N'',99), + (N'',44), + (N'̷',58); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',89), + (N'ż',2), + (N'',57), + (N'',44), + (N'Զ',33), + (N'',82), + (N'',24), + (N'Ҧ',90), + (N'',77), + (N'Զ',100); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'Τ',91), + (N'',11), + (N'',58), + (N'Ҧ',73), + (N'Ҧ',18), + (N'',21), + (N'',17), + (N'',14), + (N'',45), + (N'ܺ',3); +INSERT INTO Study.dbo.Student (Name,Age) VALUES + (N'',97), + (N'Ԋ',84), + (N'',56), + (N'л',93), + (N'',29), + (N'Զ',16), + (N'',80), + (N'',96), + (N'Ԋ',71), + (N'Զ',8); + + diff --git a/Docs/assets/database/Study.db b/Docs/assets/database/Study.db new file mode 100644 index 0000000..bea5d68 Binary files /dev/null and b/Docs/assets/database/Study.db differ diff --git a/Docs/assets/images/NuGet1.jpg b/Docs/assets/images/NuGet1.jpg new file mode 100644 index 0000000..84471c9 Binary files /dev/null and b/Docs/assets/images/NuGet1.jpg differ diff --git a/Docs/assets/images/NuGet2.jpg b/Docs/assets/images/NuGet2.jpg new file mode 100644 index 0000000..a2a2bb7 Binary files /dev/null and b/Docs/assets/images/NuGet2.jpg differ diff --git a/Docs/assets/images/csdn模板.jpg b/Docs/assets/images/csdn模板.jpg new file mode 100644 index 0000000..1905da3 Binary files /dev/null and b/Docs/assets/images/csdn模板.jpg differ diff --git a/Docs/assets/images/microsoft.jpg b/Docs/assets/images/microsoft.jpg new file mode 100644 index 0000000..02e1f61 Binary files /dev/null and b/Docs/assets/images/microsoft.jpg differ diff --git a/Docs/config.json b/Docs/config.json new file mode 100644 index 0000000..5a1d18b --- /dev/null +++ b/Docs/config.json @@ -0,0 +1,9 @@ +{ + "Database":{ + "SQLServer":"Server=.\\SQL2019;Database=study;User Id=sa;Password=gly-bicijinlian;TrustServerCertificate=true;", + "MySQL":"Server=localhost;Port=3306;Database=Study;Uid=sa;Pwd=mysql-461400;", + "PSQL":"Host=localhost;Port=5432;Username=postgres;Password=psql-461400;Database=Study;", + "SQLite":"Data Source=.\\assets\\database\\Study.db;", + "DuckDB":"Data Source=:memory:?cache=shared" + } +} \ No newline at end of file diff --git a/Docs/sqlite/SQLiteDemo.db b/Docs/sqlite/SQLiteDemo.db deleted file mode 100644 index be6259b..0000000 Binary files a/Docs/sqlite/SQLiteDemo.db and /dev/null differ diff --git a/Docs/多语言笔记.1.2.显示格式化.ipynb b/Docs/多语言笔记.1.2.显示格式化.ipynb new file mode 100644 index 0000000..e42b31a --- /dev/null +++ b/Docs/多语言笔记.1.2.显示格式化.ipynb @@ -0,0 +1,1297 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "40dc2502", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "单元格输出的格式化\n", + "================" + ] + }, + { + "cell_type": "markdown", + "id": "1dcd22f8", + "metadata": {}, + "source": [ + "## 格式化输出" + ] + }, + { + "cell_type": "markdown", + "id": "5ba9817e", + "metadata": {}, + "source": [ + "基于 .NET Interactive 的工具(包括 Polyglot 笔记本、Jupyter 和其他工具)的输出是通过 .NET Interactive 格式化器生成的,这是一组位于 Microsoft.DotNet.Interactive.Formatting 命名空间下的 API。这些 API 可以作为一个 NuGet 包独立于笔记本使用。\n", + "格式化器创建对象的字符串表示,这些字符串表示可以从纯文本到 HTML,再到像 JSON 和 CSV 这样的机器可读格式。\n", + "\n", + "以下是一些你可以在笔记本中编写的代码示例,这些代码会导致对象被格式化以供显示:\n", + "- C# 单元格末尾的返回语句或尾随表达式\n", + "- F# 单元格末尾的尾随表达式\n", + "- 调用 Display 和 ToDisplayString 扩展方法,这些方法对 C# 和 F# 中的所有对象都可用\n", + "- 在 PowerShell 单元格中调用 Out-Display\n", + "\n", + "格式化器还用于在多语言笔记本变量视图中格式化.NET对象的输出显示。其他语言的值格式化并不依赖于.NET。\n", + "> `格式化` 指的是创建对象字符串表示的过程。此过程由.NET Interactive内核通过此处所述的API实现。当格式化后的字符串在 VS Code 或 JupyterLab 中的笔记本上显示时,这一过程被称为`渲染`" + ] + }, + { + "cell_type": "markdown", + "id": "bfda8369", + "metadata": {}, + "source": [ + "## MIME类型 与 Display显示" + ] + }, + { + "cell_type": "markdown", + "id": "3800f1fa", + "metadata": {}, + "source": [ + "对于任何一个给定的对象,可以有多种不同的字符串表示方式。这些不同的表示方式都有对应的MIME类型,这些类型由简短的字符串标识,例如`text/html`或`application/json`。MIME类型可以用来通过Display扩展方法请求特定格式的对象显示,这个方法可以用于任何对象。\n", + "\n", + "例如,我们可以调用rect.Display()来显示分配给变量rect的Rectangle对象" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Submission#27+Rectangle
Width
100
Height
50
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Submission#27+Rectangle
Width
100
Height
50
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "//注意:System.Drawing不能跨平台,只在Windows系统中使用。\n", + "//不知道为啥:官方要选个不跨平台的示例\n", + "using System.Drawing;\n", + "var ract = new Rectangle\n", + "{\n", + " Height = 50,\n", + " Width = 100,\n", + "};\n", + "\n", + "//默认为 text/html,下面两种方式的效果是一样的\n", + "ract.Display();\n", + "ract.Display(\"text/html\");" + ] + }, + { + "cell_type": "markdown", + "id": "3bc132ae", + "metadata": {}, + "source": [ + "注意,Polyglot 笔记本中默认的 MIME 类型是 text/html。这可能会因 .NET 类型的不同而有所变化,但在上述示例中,矩形类型尚未应用任何自定义设置。(将在下面展示更多关于如何进行自定义设置的内容。)\n", + "> 注意:对于 C# 或 F# 中单元格的返回值,只能使用默认 MIME 类型的格式化程序。" + ] + }, + { + "cell_type": "markdown", + "id": "4d2d0a0a", + "metadata": {}, + "source": [ + "在使用Display时,可以指定不同于默认的MIME类型。只需将所需的MIME类型作为参数传递即可,例如:rect.Display(\"text/plain\")" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Rectangle\r\n", + " Width: 100\r\n", + " Height: 50" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ract.Display(\"text/plain\");" + ] + }, + { + "cell_type": "markdown", + "id": "62941e56", + "metadata": {}, + "source": [ + "另一种常见的MIME类型是application/json。在Polyglot笔记本中使用此MIME类型时,对象使用System.Text.Json进行格式化。\n", + "\n", + "执行下面的单元格,会以Json格式输出。JSON输出中的代码颜色由 VS Code 笔记本渲染器针对`application/json`类型提供。" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "application/json": { + "Height": 50, + "Width": 100 + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ract.Display(\"application/json\");" + ] + }, + { + "cell_type": "markdown", + "id": "c69d8a8e", + "metadata": {}, + "source": [ + "## 自定义格式化" + ] + }, + { + "cell_type": "markdown", + "id": "d65a2d3a", + "metadata": {}, + "source": [ + ".NET Interactive的格式化API是高度可配置的。\n", + "\n", + "可以使用`Microsoft.DotNet.Interactive.Formatting`中的代码,调整格式化行为的方式。" + ] + }, + { + "cell_type": "markdown", + "id": "86f3a920", + "metadata": {}, + "source": [ + "### 限制输出数量\n", + "在格式化序列时,例如数组或实现IEnumerable的对象,.NET Interactive的格式化器会将它们展开,以便你可以看到其中的值。\n", + "\n", + "如果执行结果集太多,默认情况下只会输出前面很少项,剩余的数据以 `...More` 代替。" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
indexvalue
0
{ Id = 1, Age = 7, Name = 韦子异 }
Id
1
Age
7
Name
韦子异
1
{ Id = 2, Age = 18, Name = 姚宇宁 }
Id
2
Age
18
Name
姚宇宁
2
{ Id = 3, Age = 2, Name = 傅子异 }
Id
3
Age
2
Name
傅子异
3
{ Id = 4, Age = 29, Name = 朱子韬 }
Id
4
Age
29
Name
朱子韬
4
{ Id = 5, Age = 85, Name = 林杰宏 }
Id
5
Age
85
Name
林杰宏
5
{ Id = 6, Age = 76, Name = 胡璐 }
Id
6
Age
76
Name
胡璐
6
{ Id = 7, Age = 88, Name = 周璐 }
Id
7
Age
88
Name
周璐
7
{ Id = 8, Age = 88, Name = 田秀英 }
Id
8
Age
88
Name
田秀英
8
{ Id = 9, Age = 19, Name = 姜詩涵 }
Id
9
Age
19
Name
姜詩涵
9
{ Id = 10, Age = 44, Name = 蔡秀英 }
Id
10
Age
44
Name
蔡秀英
10
{ Id = 11, Age = 12, Name = 张睿 }
Id
11
Age
12
Name
张睿
11
{ Id = 12, Age = 94, Name = 金嘉伦 }
Id
12
Age
94
Name
金嘉伦
12
{ Id = 13, Age = 73, Name = 萧致远 }
Id
13
Age
73
Name
萧致远
13
{ Id = 14, Age = 90, Name = 赵致远 }
Id
14
Age
90
Name
赵致远
14
{ Id = 15, Age = 82, Name = 蒋宇宁 }
Id
15
Age
82
Name
蒋宇宁
15
{ Id = 16, Age = 38, Name = 顾震南 }
Id
16
Age
38
Name
顾震南
16
{ Id = 17, Age = 15, Name = 余安琪 }
Id
17
Age
15
Name
余安琪
17
{ Id = 18, Age = 74, Name = 熊岚 }
Id
18
Age
74
Name
熊岚
18
{ Id = 19, Age = 19, Name = 卢子韬 }
Id
19
Age
19
Name
卢子韬
19
{ Id = 20, Age = 44, Name = 孔杰宏 }
Id
20
Age
44
Name
孔杰宏
... (more)
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "var names = new string[]\n", + "{\n", + " \"吕宇宁\", \"韦子异\", \"姚宇宁\", \"傅子异\", \"朱子韬\", \"林杰宏\", \"胡璐\", \"周璐\", \"田秀英\", \"姜詩涵\", \"蔡秀英\", \"张睿\", \"金嘉伦\", \"萧致远\", \"赵致远\", \"蒋宇宁\", \"顾震南\", \"余安琪\", \"熊岚\", \"卢子韬\",\n", + " \"孔杰宏\", \"周子韬\", \"黄睿\", \"史璐\", \"赵震南\", \"杜安琪\", \"赵致远\", \"石詩涵\", \"龚杰宏\", \"丁安琪\", \"黄杰宏\", \"傅睿\", \"戴嘉伦\", \"郝杰宏\", \"傅晓明\", \"孟嘉伦\", \"段睿\", \"戴致远\", \"石安琪\", \"汪詩涵\",\n", + " \"贾云熙\", \"邱子韬\", \"吴杰宏\", \"贾岚\", \"曾震南\", \"许云熙\", \"吴宇宁\", \"唐岚\", \"常嘉伦\", \"曾岚\", \"袁嘉伦\", \"黄晓明\", \"韦致远\", \"莫安琪\", \"丁子韬\", \"雷云熙\", \"许秀英\", \"朱宇宁\", \"黎詩涵\", \"贾晓明\", \n", + " \"孔詩涵\", \"秦宇宁\", \"方子韬\", \"邵秀英\", \"冯宇宁\", \"何晓明\", \"方嘉伦\", \"熊秀英\", \"沈云熙\", \"顾秀英\", \"许致远\", \"胡宇宁\", \"陶子异\", \"叶安琪\", \"邱震南\", \"刘子异\", \"周宇宁\", \"黄云熙\", \"龚杰宏\", \"杜秀英\", \n", + " \"向子异\", \"马睿\", \"黄安琪\", \"于安琪\", \"金嘉伦\", \"龚璐\", \"杨致远\", \"戴嘉伦\", \"钟詩涵\", \"阎詩涵\", \"雷安琪\", \"宋杰宏\", \"田致远\", \"冯致远\", \"雷杰宏\", \"雷子异\", \"叶璐\", \"王子异\", \"冯子韬\", \"史宇宁\"\n", + "};\n", + "\n", + "var students = Enumerable.Range(1,50).Select(s => new {Id = s, Age = Random.Shared.Next(1,100), Name = names[s]});\n", + "students.Display();" + ] + }, + { + "cell_type": "markdown", + "id": "e9e5f666", + "metadata": {}, + "source": [ + "Formatter.ListExpansionLimit 更改为自定义值" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
indexvalue
0
{ Id = 1, Age = 18, Name = 韦子异 }
Id
1
Age
18
Name
韦子异
1
{ Id = 2, Age = 89, Name = 姚宇宁 }
Id
2
Age
89
Name
姚宇宁
2
{ Id = 3, Age = 52, Name = 傅子异 }
Id
3
Age
52
Name
傅子异
3
{ Id = 4, Age = 32, Name = 朱子韬 }
Id
4
Age
32
Name
朱子韬
4
{ Id = 5, Age = 73, Name = 林杰宏 }
Id
5
Age
73
Name
林杰宏
... (more)
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "Microsoft.DotNet.Interactive.Formatting.Formatter.ListExpansionLimit = 5;\n", + "students.Display();" + ] + }, + { + "cell_type": "markdown", + "id": "55513f2a", + "metadata": {}, + "source": [ + "上面的示例中,通过设置Formatter.ListExpansionLimit = 5,然后显示相同的列表对象,.NET Interactive现在仅显示前五项,后面跟着 ...(more)。\n", + "\n", + "也可以通过设置`Formatter.ListExpansionLimit`来限制特定类型的输出。需要注意的是,这里的类型T必须与列表中的项完全匹配。\n", + "\n", + "以下是一个使用int类型的示例:" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
[ 1, 2, 3 ... (7 more) ]
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "Microsoft.DotNet.Interactive.Formatting.Formatter.ListExpansionLimit = 3;\n", + "Enumerable.Range(1, 10).Display();\n" + ] + }, + { + "cell_type": "markdown", + "id": "c30384b0", + "metadata": {}, + "source": [ + "注意:有些以 ...(more)结尾,有些以(数字 more)结尾。\n", + "\n", + "这是因为:List、List、数组等,列举前就知道元素确切的数量,以 `(数字 more)`结尾;而像 IEnumerable(Enumerable.Range 返回类型是IEnumerable)之类的,因此在枚举整个序列之前,无法知道元素确切的数量;在这种情况下,.NET交互式格式化器在达到配置的ListExpansionLimit时会停止,并不会继续计数剩余的序列, 以 `...(more)` 结尾" + ] + }, + { + "cell_type": "markdown", + "id": "8ce3b66a", + "metadata": {}, + "source": [ + "### 限制对象循环引用次数" + ] + }, + { + "cell_type": "markdown", + "id": "79e36f3f", + "metadata": {}, + "source": [ + "有些对象存在引用循环。虽然.NET Interactive格式化器会遍历对象图,但它为了避免输出过大和无限递归,只会递归到特定深度。\n", + "\n", + "以下是一个C#代码示例,它定义了一个简单的Node类,创建了一个引用循环,并使用C#脚本的尾随表达式(相当于返回语句)对其进行格式化:" + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Submission#93+Node
Next
Submission#93+Node
Next
Submission#93+Node
Next
Submission#93+Node
Next
Submission#93+Node
Next
Submission#93+Node
NextSubmission#93+Node
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "public class Node\n", + "{\n", + " public Node Next { get; set; } \n", + "}\n", + "\n", + "Node node1 = new();\n", + "Node node2 = new();\n", + "\n", + "node1.Next = node2;\n", + "node2.Next = node1;\n", + "\n", + "node1" + ] + }, + { + "cell_type": "markdown", + "id": "0cdad28f", + "metadata": {}, + "source": [ + "这表明格式化器在格式化到深度6后停止了递归。这个深度可以通过Formatter.RecursionLimit方法进行更改:" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Submission#93+Node
Next
Submission#93+Node
NextSubmission#93+Node
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "Microsoft.DotNet.Interactive.Formatting.Formatter.RecursionLimit = 2;\n", + "node1" + ] + }, + { + "cell_type": "markdown", + "id": "9ae2d29c", + "metadata": {}, + "source": [ + "### 首选 MIME 类型" + ] + }, + { + "cell_type": "markdown", + "id": "210ac005", + "metadata": {}, + "source": [ + "前面提到,Polyglot 笔记本中用于格式化的默认 MIME 类型是 text/html。当使用 Display() 方法时,如果没有向 mimeType 参数传递值,或者在 C# 或 F# 中使用 return 语句或尾随表达式时,就会应用这个默认设置。这个默认设置可以全局更改,也可以针对特定类型更改。\n", + "\n", + "以下示例将 Rectangle 的默认值更改为 text/plain。" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Student\r\n", + " Id: 1\r\n", + " Name: 张三\r\n", + " Age: 55" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "public class Student\n", + "{\n", + " public int Id {get;set;}\n", + " public string Name {get;set;}\n", + " public int Age {get;set;}\n", + "}\n", + "\n", + "Microsoft.DotNet.Interactive.Formatting.Formatter.SetPreferredMimeTypesFor(typeof(Student), \"text/plain\");\n", + "\n", + "new Student\n", + "{ \n", + " Id = 1,\n", + " Name = \"张三\",\n", + " Age = 55\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "e2d42a41", + "metadata": {}, + "source": [ + "该方法可用于设置多个首选MIME类型。第二个参数是params参数,它允许您传递多个值。" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "application/json": { + "Age": 55, + "Id": 1, + "Name": "张三" + }, + "text/plain": [ + "Student\r\n", + " Id: 1\r\n", + " Name: 张三\r\n", + " Age: 55" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "Microsoft.DotNet.Interactive.Formatting.Formatter.SetPreferredMimeTypesFor\n", + "(\n", + " typeof(Student), \n", + " \"text/plain\",\n", + " \"application/json\"\n", + ");\n", + "\n", + "new Student\n", + "{ \n", + " Id = 1,\n", + " Name = \"张三\",\n", + " Age = 55\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "24305cfd", + "metadata": {}, + "source": [ + "注册多个MIME时,可以切换输出格式:\n", + "单击 执行结果单元格的最左侧`...`, 选择 `更改演示文稿`后,在VS Code最上访,会弹出选择窗口,选择注册项中的一个,就可以重新以选中项的格式重新显示结果。" + ] + }, + { + "cell_type": "markdown", + "id": "058b472e", + "metadata": {}, + "source": [ + "### 替换默认的格式化类型" + ] + }, + { + "cell_type": "markdown", + "id": "15eeab9b", + "metadata": {}, + "source": [ + "默认格式化器通常通过打印列表和属性来显示对象的值。输出主要是文本形式。如果你希望以不同的方式显示某种类型的内容,无论是不同的文本输出、图像还是图表,你可以通过为特定类型注册自定义格式化器来实现。这些类型可以是你自己定义的,也可以是其他.NET库中定义的。\n", + "\n", + "一个常见的使用自定义格式化器的场景是渲染图表。一些NuGet包,如Plotly.NET,提供了.NET Interactive扩展,利用此功能以交互式的HTML和JavaScript为基础生成输出。\n", + "\n", + "注册自定义格式化器最简单的方法是使用Formatter.Register方法,它有几个不同的重载版本。在笔记本中使用最友好、最方便的一个接受两个参数:\n", + "+ 委托:它接受你要注册的类型的对象,并返回一个字符串。在这里,你可以指定所需的字符串转换;\n", + "+ MIME类型:只有当使用此MIME类型时,才会调用你的自定义格式化器\n", + "\n", + "下面的示例将 Rectangles 类的实例格式化为SVG矩形。" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "id": "494ec543", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "public class Rectangle\n", + "{\n", + " public int Width {get;set;}\n", + " public int Height {get;set;}\n", + "}\n", + "\n", + "Microsoft.DotNet.Interactive.Formatting.Formatter.Register\n", + "(\n", + " formatter: //格式化方法:把类型对象,转化为输出字符串\n", + " rect => $\"\"\"\n", + " \n", + " \n", + " \n", + " \"\"\", \n", + " mimeType: //输出媒体类型\n", + " \"text/html\"\n", + ");" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "\r\n", + " \r\n", + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "/*\n", + "运行此代码后,Rectangle对象将显示为图形矩形,而不是属性值列表。\n", + "(以下示例使用C#脚本尾随表达式语法,该语法通常配置为在笔记本中使用text/html MIME类型。)\n", + "*/\n", + "new Rectangle(){Width = 100, Height = 50}" + ] + }, + { + "cell_type": "markdown", + "id": "363d55e9", + "metadata": {}, + "source": [ + "特别指出:当在列表中遇到自定义类型或作为对象属性时,仍将调用自定义格式化程序" + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
indexvalue
0\r\n", + " \r\n", + "
1\r\n", + " \r\n", + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "new[] \n", + "{\n", + " new Rectangle(){Width = 200, Height = 50},\n", + " new Rectangle(){Width = 200, Height = 100}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "id": "c6fd6734", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
{ Name = Example, Rectangle = Submission#97+Rectangle }
Name
Example
Rectangle\r\n", + " \r\n", + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "//具有 Rectangle 类型属性的匿名对象\n", + "new {\n", + " Name = \"Example\",\n", + " Rectangle = new Rectangle(){ Width=100, Height=50 }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "39dab7b0", + "metadata": {}, + "source": [ + "### 打开泛型类型" + ] + }, + { + "cell_type": "markdown", + "id": "3606e605", + "metadata": {}, + "source": [ + "可以通过使用开放泛型类型定义作为键来指定格式化程序。以下代码将为所有类型的 T 的 List 变体注册一个格式化程序,并打印每个元素及其哈希代码。(请注意,必须强制转换对象才能迭代其项。" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "Microsoft.DotNet.Interactive.Formatting.Formatter.Register\n", + "(\n", + " type: typeof(List<>),\n", + " formatter: (list, writer) =>\n", + " {\n", + " foreach (var obj in (IEnumerable)list)\n", + " {\n", + " writer.WriteLine($\"{obj} ({obj.GetHashCode()})\");\n", + " }\n", + " }, \"text/html\"\n", + ");" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "one (1556465726)\r\n", + "two (401392997)\r\n", + "three (-257294126)\r\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "//运行上述代码后,以下内容将不再仅打印列表中的值 [\"one\",\"two\",\"three\"]\n", + "//变为:one (254814599) two (656421459) three (-1117028319)\n", + "var list = new List { \"one\", \"two\", \"three\" };\n", + "list" + ] + }, + { + "cell_type": "markdown", + "id": "a8b71f19", + "metadata": {}, + "source": [ + "### TypeFormatterSource 特性类\n", + "Formatter.Register方式外,另一种注册自定义格式化程序的方式是:使用 TypeFormatterSourceAttribute 修饰类型。如果您想直接在笔记本中重新定义格式化程序设置,这不是最方便的方法。但是,如果您正在编写 .NET Interactive 扩展,或者编写包含某些类型的自定义格式的库或应用程序,则建议使用此方法。其中一个原因是基于属性的方法更简单。另一个原因是,调用 Formatter.ResetToDefault() 时不会清除基于属性的格式化程序自定义,而使用 Formatter.Register 配置的格式化程序会被清除。您可以将基于属性的注册方法视为为类型设置默认格式的一种方式。\n", + "\n", + "基于属性的格式化程序注册有两种方法:一种用于项目引用时,另一种用于项目不引用 Microsoft.DotNet.Interactive.Formatting 时\n", + "\n", + "如果您已经引用了 Microsoft.DotNet.Interactive.Formatting ,例如,因为您正在编写 .NET Interactive 扩展,那么您可以使用 中定义的 TypeFormatterSourceAttribute 来修饰需要自定义格式的类型 Microsoft.DotNet.Interactive.Formatting 。下面是一个示例:" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "[Microsoft.DotNet.Interactive.Formatting.TypeFormatterSource(typeof(MyFormatterSource))]\n", + "public class MyTypeWithCustomFormatting\n", + "{\n", + "\n", + "}\n", + "\n", + "//带Mime类型\n", + "[Microsoft.DotNet.Interactive.Formatting.TypeFormatterSource\n", + "(\n", + " typeof(MyFormatterSource), PreferredMimeTypes = new[] { \"text/html\", \"application/json\" }\n", + ")]\n", + "public class MyTypeWithCustomFormatting2\n", + "{\n", + "}\n", + "\n", + "//TypeFormatterSourceAttribute 指定的格式化程序源必须实现 ITypeFormatterSource,并且必须具有空构造函数。它不需要是 public 类型\n", + "public class MyFormatterSource : Microsoft.DotNet.Interactive.Formatting.ITypeFormatterSource\n", + "{\n", + " public IEnumerable CreateTypeFormatters()\n", + " {\n", + " return new Microsoft.DotNet.Interactive.Formatting.ITypeFormatter[]\n", + " {\n", + " new Microsoft.DotNet.Interactive.Formatting.PlainTextFormatter(context => \n", + " $\"Hello from {nameof(MyFormatterSource)} using MIME type text/plain\"),\n", + " new Microsoft.DotNet.Interactive.Formatting.HtmlFormatter(context => \n", + " $\"Hello from {nameof(MyFormatterSource)} using MIME type text/html\")\n", + " };\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "6437f82e", + "metadata": {}, + "source": [ + "一个完整例子:" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "[AttributeUsage(AttributeTargets.Class)]\n", + "internal class TypeFormatterSourceAttribute : Attribute\n", + "{\n", + " public TypeFormatterSourceAttribute(Type formatterSourceType)\n", + " {\n", + " FormatterSourceType = formatterSourceType;\n", + " }\n", + "\n", + " public Type FormatterSourceType { get; }\n", + "\n", + " public string[] PreferredMimeTypes { get; set; }\n", + "}\n", + "\n", + "internal class MyConventionBasedFormatterSource\n", + "{\n", + " public IEnumerable CreateTypeFormatters()\n", + " {\n", + " yield return new MyConventionBasedFormatter { MimeType = \"text/html\" };\n", + " }\n", + "}\n", + "\n", + "internal class MyConventionBasedFormatter\n", + "{\n", + " public string MimeType { get; set; }\n", + "\n", + " public bool Format(object instance, System.IO.TextWriter writer)\n", + " {\n", + " if (instance is MyTypeWithCustomFormatting myObj)\n", + " {\n", + " writer.Write($\"
Custom formattering for {myObj}
\");\n", + " return true;\n", + " }\n", + " else\n", + " {\n", + " return false;\n", + " }\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "fbf04c96", + "metadata": {}, + "source": [ + "### 重置格式设置\n", + "在尝试不同的格式设置配置时,您可能会发现需要将所有内容重置为首次启动内核时看到的默认值。您可以轻松执行此作:" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "Microsoft.DotNet.Interactive.Formatting.Formatter.ResetToDefault();" + ] + }, + { + "cell_type": "markdown", + "id": "575b3a6a", + "metadata": {}, + "source": [ + "### 如何选择格式化程序\n", + "可以注册多个可能适用于同一类型的格式化程序。例如,可以为 object、IEnumerable 和 IList 注册格式化程序,其中任何一个都可能合理地应用于 List 的实例。由于这些原因,了解如何选择 formatter 可能很有用。" + ] + }, + { + "cell_type": "markdown", + "id": "d4aaa243", + "metadata": {}, + "source": [ + "为 A 类型的对象选择适用的格式化程序,如下所示:\n", + "+ 选择 MIME 类型:\n", + " + 选择与 A 相关的最具体的用户注册 MIME 类型首选项\n", + " + 如果没有相关的用户注册的 MIME 类型,则使用配置的默认 MIME 类型\n", + "+ 选择一个格式化程序:\n", + " + 选择与 A 相关的最具体的用户注册格式化程序\n", + " + 如果没有相关的用户注册格式化程序,则选择默认格式化程序\n", + "\n", + "> 在这里,“最具体”是指类和接口层次结构。如果顺序完全一致或存在其他冲突,则首选较新的注册。当泛型类型的类型定义相同时,泛型类型的类型实例化优先于泛型格式化程序。\n", + "> MIME 类型的默认格式化程序集始终包括 object 的格式化程序" + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "
Submission#97+Rectangle
Width
100
Height
50
\r\n" + ] + } + ], + "source": [ + "using System.IO;\n", + "using Microsoft.DotNet.Interactive.Formatting;\n", + "\n", + "ITypeFormatter formatter = Formatter.GetPreferredFormatterFor( typeof(Rectangle), Formatter.DefaultMimeType);\n", + "\n", + "var rect = new Rectangle { Width = 100, Height = 50 };\n", + "\n", + "var writer = new StringWriter();\n", + "\n", + "formatter.Format(rect, writer);\n", + "\n", + "Console.WriteLine(writer.ToString());" + ] + }, + { + "cell_type": "markdown", + "id": "6cbb3edb", + "metadata": {}, + "source": [ + "Examples 例子, 用于说明 Formatter 选择的工作原理\n", + "\n", + "+ 如果您为类型 A 注册格式化程序,则该格式化程序将用于类型 A 的所有对象(直到稍后指定类型 A 的替代格式化程序)\n", + "+ 如果为 System.Object 注册格式化程序,则它优先于所有其他格式化程序,但其他更具体的用户定义的格式化程序除外\n", + "+ 如果为任何 sealed 类型注册格式化程序,则它优先于所有其他格式化程序(除非为该类型指定了更多格式化程序)\n", + "+ 如果注册 List<> 和 List 格式化程序,则 List 格式化程序优先用于 List 类型的对象,而 List<> 格式化程序优先用于其他泛型实例化,例如 List" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "languageName": "csharp", + "name": "csharp" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Docs/多语言笔记.1.2.显示格式化.md b/Docs/多语言笔记.1.2.显示格式化.md new file mode 100644 index 0000000..d4335e9 --- /dev/null +++ b/Docs/多语言笔记.1.2.显示格式化.md @@ -0,0 +1,336 @@ +单元格输出的格式化 +================ +## 格式化输出 +基于 .NET Interactive 的工具(包括 Polyglot 笔记本、Jupyter 和其他工具)的输出是通过 .NET Interactive 格式化器生成的,这是一组位于 Microsoft.DotNet.Interactive.Formatting 命名空间下的 API。这些 API 可以作为一个 NuGet 包独立于笔记本使用。 +格式化器创建对象的字符串表示,这些字符串表示可以从纯文本到 HTML,再到像 JSON 和 CSV 这样的机器可读格式。 + +以下是一些你可以在笔记本中编写的代码示例,这些代码会导致对象被格式化以供显示: +- C# 单元格末尾的返回语句或尾随表达式 +- F# 单元格末尾的尾随表达式 +- 调用 Display 和 ToDisplayString 扩展方法,这些方法对 C# 和 F# 中的所有对象都可用 +- 在 PowerShell 单元格中调用 Out-Display + +格式化器还用于在多语言笔记本变量视图中格式化.NET对象的输出显示。其他语言的值格式化并不依赖于.NET。 +> `格式化` 指的是创建对象字符串表示的过程。此过程由.NET Interactive内核通过此处所述的API实现。当格式化后的字符串在 VS Code 或 JupyterLab 中的笔记本上显示时,这一过程被称为`渲染` +## MIME类型 与 Display显示 +对于任何一个给定的对象,可以有多种不同的字符串表示方式。这些不同的表示方式都有对应的MIME类型,这些类型由简短的字符串标识,例如`text/html`或`application/json`。MIME类型可以用来通过Display扩展方法请求特定格式的对象显示,这个方法可以用于任何对象。 + +例如,我们可以调用rect.Display()来显示分配给变量rect的Rectangle对象 +```csharp +//注意:System.Drawing不能跨平台,只在Windows系统中使用。 +//不知道为啥:官方要选个不跨平台的示例 +using System.Drawing; +var ract = new Rectangle +{ + Height = 50, + Width = 100, +}; + +//默认为 text/html,下面两种方式的效果是一样的 +ract.Display(); +ract.Display("text/html"); +``` +注意,Polyglot 笔记本中默认的 MIME 类型是 text/html。这可能会因 .NET 类型的不同而有所变化,但在上述示例中,矩形类型尚未应用任何自定义设置。(将在下面展示更多关于如何进行自定义设置的内容。) +> 注意:对于 C# 或 F# 中单元格的返回值,只能使用默认 MIME 类型的格式化程序。 +在使用Display时,可以指定不同于默认的MIME类型。只需将所需的MIME类型作为参数传递即可,例如:rect.Display("text/plain") +```csharp +ract.Display("text/plain"); +``` +另一种常见的MIME类型是application/json。在Polyglot笔记本中使用此MIME类型时,对象使用System.Text.Json进行格式化。 + +执行下面的单元格,会以Json格式输出。JSON输出中的代码颜色由 VS Code 笔记本渲染器针对`application/json`类型提供。 +```csharp +ract.Display("application/json"); +``` +## 自定义格式化 +.NET Interactive的格式化API是高度可配置的。 + +可以使用`Microsoft.DotNet.Interactive.Formatting`中的代码,调整格式化行为的方式。 +### 限制输出数量 +在格式化序列时,例如数组或实现IEnumerable的对象,.NET Interactive的格式化器会将它们展开,以便你可以看到其中的值。 + +如果执行结果集太多,默认情况下只会输出前面很少项,剩余的数据以 `...More` 代替。 +```csharp +var names = new string[] +{ + "吕宇宁", "韦子异", "姚宇宁", "傅子异", "朱子韬", "林杰宏", "胡璐", "周璐", "田秀英", "姜詩涵", "蔡秀英", "张睿", "金嘉伦", "萧致远", "赵致远", "蒋宇宁", "顾震南", "余安琪", "熊岚", "卢子韬", + "孔杰宏", "周子韬", "黄睿", "史璐", "赵震南", "杜安琪", "赵致远", "石詩涵", "龚杰宏", "丁安琪", "黄杰宏", "傅睿", "戴嘉伦", "郝杰宏", "傅晓明", "孟嘉伦", "段睿", "戴致远", "石安琪", "汪詩涵", + "贾云熙", "邱子韬", "吴杰宏", "贾岚", "曾震南", "许云熙", "吴宇宁", "唐岚", "常嘉伦", "曾岚", "袁嘉伦", "黄晓明", "韦致远", "莫安琪", "丁子韬", "雷云熙", "许秀英", "朱宇宁", "黎詩涵", "贾晓明", + "孔詩涵", "秦宇宁", "方子韬", "邵秀英", "冯宇宁", "何晓明", "方嘉伦", "熊秀英", "沈云熙", "顾秀英", "许致远", "胡宇宁", "陶子异", "叶安琪", "邱震南", "刘子异", "周宇宁", "黄云熙", "龚杰宏", "杜秀英", + "向子异", "马睿", "黄安琪", "于安琪", "金嘉伦", "龚璐", "杨致远", "戴嘉伦", "钟詩涵", "阎詩涵", "雷安琪", "宋杰宏", "田致远", "冯致远", "雷杰宏", "雷子异", "叶璐", "王子异", "冯子韬", "史宇宁" +}; + +var students = Enumerable.Range(1,50).Select(s => new {Id = s, Age = Random.Shared.Next(1,100), Name = names[s]}); +students.Display(); +``` +Formatter.ListExpansionLimit 更改为自定义值 +```csharp +Microsoft.DotNet.Interactive.Formatting.Formatter.ListExpansionLimit = 5; +students.Display(); +``` +上面的示例中,通过设置Formatter.ListExpansionLimit = 5,然后显示相同的列表对象,.NET Interactive现在仅显示前五项,后面跟着 ...(more)。 + +也可以通过设置`Formatter.ListExpansionLimit`来限制特定类型的输出。需要注意的是,这里的类型T必须与列表中的项完全匹配。 + +以下是一个使用int类型的示例: +```csharp +Microsoft.DotNet.Interactive.Formatting.Formatter.ListExpansionLimit = 3; +Enumerable.Range(1, 10).Display(); + +``` +注意:有些以 ...(more)结尾,有些以(数字 more)结尾。 + +这是因为:List、List、数组等,列举前就知道元素确切的数量,以 `(数字 more)`结尾;而像 IEnumerable(Enumerable.Range 返回类型是IEnumerable)之类的,因此在枚举整个序列之前,无法知道元素确切的数量;在这种情况下,.NET交互式格式化器在达到配置的ListExpansionLimit时会停止,并不会继续计数剩余的序列, 以 `...(more)` 结尾 +### 限制对象循环引用次数 +有些对象存在引用循环。虽然.NET Interactive格式化器会遍历对象图,但它为了避免输出过大和无限递归,只会递归到特定深度。 + +以下是一个C#代码示例,它定义了一个简单的Node类,创建了一个引用循环,并使用C#脚本的尾随表达式(相当于返回语句)对其进行格式化: +```csharp +public class Node +{ + public Node Next { get; set; } +} + +Node node1 = new(); +Node node2 = new(); + +node1.Next = node2; +node2.Next = node1; + +node1 +``` +这表明格式化器在格式化到深度6后停止了递归。这个深度可以通过Formatter.RecursionLimit方法进行更改: +```csharp +Microsoft.DotNet.Interactive.Formatting.Formatter.RecursionLimit = 2; +node1 +``` +### 首选 MIME 类型 +前面提到,Polyglot 笔记本中用于格式化的默认 MIME 类型是 text/html。当使用 Display() 方法时,如果没有向 mimeType 参数传递值,或者在 C# 或 F# 中使用 return 语句或尾随表达式时,就会应用这个默认设置。这个默认设置可以全局更改,也可以针对特定类型更改。 + +以下示例将 Rectangle 的默认值更改为 text/plain。 +```csharp +public class Student +{ + public int Id {get;set;} + public string Name {get;set;} + public int Age {get;set;} +} + +Microsoft.DotNet.Interactive.Formatting.Formatter.SetPreferredMimeTypesFor(typeof(Student), "text/plain"); + +new Student +{ + Id = 1, + Name = "张三", + Age = 55 +} +``` +该方法可用于设置多个首选MIME类型。第二个参数是params参数,它允许您传递多个值。 +```csharp +Microsoft.DotNet.Interactive.Formatting.Formatter.SetPreferredMimeTypesFor +( + typeof(Student), + "text/plain", + "application/json" +); + +new Student +{ + Id = 1, + Name = "张三", + Age = 55 +} +``` +注册多个MIME时,可以切换输出格式: +单击 执行结果单元格的最左侧`...`, 选择 `更改演示文稿`后,在VS Code最上访,会弹出选择窗口,选择注册项中的一个,就可以重新以选中项的格式重新显示结果。 +### 替换默认的格式化类型 +默认格式化器通常通过打印列表和属性来显示对象的值。输出主要是文本形式。如果你希望以不同的方式显示某种类型的内容,无论是不同的文本输出、图像还是图表,你可以通过为特定类型注册自定义格式化器来实现。这些类型可以是你自己定义的,也可以是其他.NET库中定义的。 + +一个常见的使用自定义格式化器的场景是渲染图表。一些NuGet包,如Plotly.NET,提供了.NET Interactive扩展,利用此功能以交互式的HTML和JavaScript为基础生成输出。 + +注册自定义格式化器最简单的方法是使用Formatter.Register方法,它有几个不同的重载版本。在笔记本中使用最友好、最方便的一个接受两个参数: ++ 委托:它接受你要注册的类型的对象,并返回一个字符串。在这里,你可以指定所需的字符串转换; ++ MIME类型:只有当使用此MIME类型时,才会调用你的自定义格式化器 + +下面的示例将 Rectangles 类的实例格式化为SVG矩形。 +```csharp +public class Rectangle +{ + public int Width {get;set;} + public int Height {get;set;} +} + +Microsoft.DotNet.Interactive.Formatting.Formatter.Register +( + formatter: //格式化方法:把类型对象,转化为输出字符串 + rect => $""" + + + + """, + mimeType: //输出媒体类型 + "text/html" +); +``` +```csharp +/* +运行此代码后,Rectangle对象将显示为图形矩形,而不是属性值列表。 +(以下示例使用C#脚本尾随表达式语法,该语法通常配置为在笔记本中使用text/html MIME类型。) +*/ +new Rectangle(){Width = 100, Height = 50} +``` +特别指出:当在列表中遇到自定义类型或作为对象属性时,仍将调用自定义格式化程序 +```csharp +new[] +{ + new Rectangle(){Width = 200, Height = 50}, + new Rectangle(){Width = 200, Height = 100} +} +``` +```csharp +//具有 Rectangle 类型属性的匿名对象 +new { + Name = "Example", + Rectangle = new Rectangle(){ Width=100, Height=50 } +} +``` +### 打开泛型类型 +可以通过使用开放泛型类型定义作为键来指定格式化程序。以下代码将为所有类型的 T 的 List 变体注册一个格式化程序,并打印每个元素及其哈希代码。(请注意,必须强制转换对象才能迭代其项。 +```csharp +Microsoft.DotNet.Interactive.Formatting.Formatter.Register +( + type: typeof(List<>), + formatter: (list, writer) => + { + foreach (var obj in (IEnumerable)list) + { + writer.WriteLine($"{obj} ({obj.GetHashCode()})"); + } + }, "text/html" +); +``` +```csharp +//运行上述代码后,以下内容将不再仅打印列表中的值 ["one","two","three"] +//变为:one (254814599) two (656421459) three (-1117028319) +var list = new List { "one", "two", "three" }; +list +``` +### TypeFormatterSource 特性类 +Formatter.Register方式外,另一种注册自定义格式化程序的方式是:使用 TypeFormatterSourceAttribute 修饰类型。如果您想直接在笔记本中重新定义格式化程序设置,这不是最方便的方法。但是,如果您正在编写 .NET Interactive 扩展,或者编写包含某些类型的自定义格式的库或应用程序,则建议使用此方法。其中一个原因是基于属性的方法更简单。另一个原因是,调用 Formatter.ResetToDefault() 时不会清除基于属性的格式化程序自定义,而使用 Formatter.Register 配置的格式化程序会被清除。您可以将基于属性的注册方法视为为类型设置默认格式的一种方式。 + +基于属性的格式化程序注册有两种方法:一种用于项目引用时,另一种用于项目不引用 Microsoft.DotNet.Interactive.Formatting 时 + +如果您已经引用了 Microsoft.DotNet.Interactive.Formatting ,例如,因为您正在编写 .NET Interactive 扩展,那么您可以使用 中定义的 TypeFormatterSourceAttribute 来修饰需要自定义格式的类型 Microsoft.DotNet.Interactive.Formatting 。下面是一个示例: +```csharp +[Microsoft.DotNet.Interactive.Formatting.TypeFormatterSource(typeof(MyFormatterSource))] +public class MyTypeWithCustomFormatting +{ + +} + +//带Mime类型 +[Microsoft.DotNet.Interactive.Formatting.TypeFormatterSource +( + typeof(MyFormatterSource), PreferredMimeTypes = new[] { "text/html", "application/json" } +)] +public class MyTypeWithCustomFormatting2 +{ +} + +//TypeFormatterSourceAttribute 指定的格式化程序源必须实现 ITypeFormatterSource,并且必须具有空构造函数。它不需要是 public 类型 +public class MyFormatterSource : Microsoft.DotNet.Interactive.Formatting.ITypeFormatterSource +{ + public IEnumerable CreateTypeFormatters() + { + return new Microsoft.DotNet.Interactive.Formatting.ITypeFormatter[] + { + new Microsoft.DotNet.Interactive.Formatting.PlainTextFormatter(context => + $"Hello from {nameof(MyFormatterSource)} using MIME type text/plain"), + new Microsoft.DotNet.Interactive.Formatting.HtmlFormatter(context => + $"Hello from {nameof(MyFormatterSource)} using MIME type text/html") + }; + } +} +``` +一个完整例子: +```csharp +[AttributeUsage(AttributeTargets.Class)] +internal class TypeFormatterSourceAttribute : Attribute +{ + public TypeFormatterSourceAttribute(Type formatterSourceType) + { + FormatterSourceType = formatterSourceType; + } + + public Type FormatterSourceType { get; } + + public string[] PreferredMimeTypes { get; set; } +} + +internal class MyConventionBasedFormatterSource +{ + public IEnumerable CreateTypeFormatters() + { + yield return new MyConventionBasedFormatter { MimeType = "text/html" }; + } +} + +internal class MyConventionBasedFormatter +{ + public string MimeType { get; set; } + + public bool Format(object instance, System.IO.TextWriter writer) + { + if (instance is MyTypeWithCustomFormatting myObj) + { + writer.Write($"
Custom formattering for {myObj}
"); + return true; + } + else + { + return false; + } + } +} +``` +### 重置格式设置 +在尝试不同的格式设置配置时,您可能会发现需要将所有内容重置为首次启动内核时看到的默认值。您可以轻松执行此作: +```csharp +Microsoft.DotNet.Interactive.Formatting.Formatter.ResetToDefault(); +``` +### 如何选择格式化程序 +可以注册多个可能适用于同一类型的格式化程序。例如,可以为 object、IEnumerable 和 IList 注册格式化程序,其中任何一个都可能合理地应用于 List 的实例。由于这些原因,了解如何选择 formatter 可能很有用。 +为 A 类型的对象选择适用的格式化程序,如下所示: ++ 选择 MIME 类型: + + 选择与 A 相关的最具体的用户注册 MIME 类型首选项 + + 如果没有相关的用户注册的 MIME 类型,则使用配置的默认 MIME 类型 ++ 选择一个格式化程序: + + 选择与 A 相关的最具体的用户注册格式化程序 + + 如果没有相关的用户注册格式化程序,则选择默认格式化程序 + +> 在这里,“最具体”是指类和接口层次结构。如果顺序完全一致或存在其他冲突,则首选较新的注册。当泛型类型的类型定义相同时,泛型类型的类型实例化优先于泛型格式化程序。 +> MIME 类型的默认格式化程序集始终包括 object 的格式化程序 +```csharp +using System.IO; +using Microsoft.DotNet.Interactive.Formatting; + +ITypeFormatter formatter = Formatter.GetPreferredFormatterFor( typeof(Rectangle), Formatter.DefaultMimeType); + +var rect = new Rectangle { Width = 100, Height = 50 }; + +var writer = new StringWriter(); + +formatter.Format(rect, writer); + +Console.WriteLine(writer.ToString()); +``` +Examples 例子, 用于说明 Formatter 选择的工作原理 + ++ 如果您为类型 A 注册格式化程序,则该格式化程序将用于类型 A 的所有对象(直到稍后指定类型 A 的替代格式化程序) ++ 如果为 System.Object 注册格式化程序,则它优先于所有其他格式化程序,但其他更具体的用户定义的格式化程序除外 ++ 如果为任何 sealed 类型注册格式化程序,则它优先于所有其他格式化程序(除非为该类型指定了更多格式化程序) ++ 如果注册 List<> 和 List 格式化程序,则 List 格式化程序优先用于 List 类型的对象,而 List<> 格式化程序优先用于其他泛型实例化,例如 List diff --git a/Docs/多语言笔记.2.1.操作数据库-SQL内核.ipynb b/Docs/多语言笔记.2.1.操作数据库-SQL内核.ipynb new file mode 100644 index 0000000..07a173d --- /dev/null +++ b/Docs/多语言笔记.2.1.操作数据库-SQL内核.ipynb @@ -0,0 +1,2078 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "82cd130a", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "操作数据库\n", + "=========" + ] + }, + { + "cell_type": "markdown", + "id": "7c1ce91f", + "metadata": {}, + "source": [ + "原理:使用#!connect命令,连接子内核进行操作。可以连接MSSQL、SQLite、PostgreSQL等;" + ] + }, + { + "cell_type": "markdown", + "id": "ed3707e0", + "metadata": {}, + "source": [ + "## 初始化" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.Extensions.Configuration, 9.0.4
  • Microsoft.Extensions.Configuration.Binder, 9.0.4
  • Microsoft.Extensions.Configuration.CommandLine, 9.0.4
  • Microsoft.Extensions.Configuration.EnvironmentVariables, 9.0.4
  • Microsoft.Extensions.Configuration.ini, 9.0.4
  • Microsoft.Extensions.Configuration.json, 9.0.4
  • Microsoft.Extensions.Configuration.KeyPerFile, 9.0.4
  • Microsoft.Extensions.Configuration.UserSecrets, 9.0.4
  • Microsoft.Extensions.Configuration.xml, 9.0.4
  • Microsoft.Extensions.DependencyInjection, 9.0.4
  • Microsoft.Extensions.Logging, 9.0.4
  • Microsoft.Extensions.Logging.Configuration, 9.0.4
  • Microsoft.Extensions.Logging.Console, 9.0.4
  • Microsoft.Extensions.Logging.Debug, 9.0.4
  • Microsoft.Extensions.Logging.EventSource, 9.0.4
  • Microsoft.Extensions.Options, 9.0.4
  • Microsoft.Extensions.Options.ConfigurationExtensions, 9.0.4
  • Microsoft.Extensions.Options.DataAnnotations, 9.0.4
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "//全局初始化\n", + "#!import \"./Base.ipynb\"\n", + "\n", + "//共享\n", + "using Microsoft.DotNet.Interactive;\n", + "using Microsoft.DotNet.Interactive.Commands;" + ] + }, + { + "cell_type": "markdown", + "id": "8373e80a", + "metadata": {}, + "source": [ + "## 连接数据库(SQL Server 2019为例)" + ] + }, + { + "cell_type": "markdown", + "id": "24e923e2", + "metadata": {}, + "source": [ + "### 第一步:C#内核单元格中,引入相关的 nuget 包\n", + "每种数据库都有自己的包,形如 Microsoft.DotNet.Interactive.DbName, SQL Server的包为 Microsoft.DotNet.Interactive.SqlServer" + ] + }, + { + "cell_type": "markdown", + "id": "eb2d3716", + "metadata": {}, + "source": [ + "+ 在 `VS Code 终端的 NuGet 包管理` 里输入 `Microsoft.DotNet.Interactive.` 查询(把预览给勾上)\n", + "![image](./assets/images/NuGet1.jpg)\n", + "\n", + "+ 在[NuGet官网](https://www.nuget.org/)搜索 `Microsoft.DotNet.Interactive.`\n", + "![image](./assets/images/NuGet2.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "75b36179", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.DotNet.Interactive.SqlServer, 1.0.0-beta.25177.1
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Loading extension script from `C:\\Users\\ruyu\\.nuget\\packages\\microsoft.dotnet.interactive.sqlserver\\1.0.0-beta.25177.1\\interactive-extensions\\dotnet\\extension.dib`" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Query Microsoft SQL Server databases.\r\n", + "

This extension adds support for connecting to Microsoft SQL Server databases using the #!connect mssql magic command. For more information, run a cell using the #!sql magic command.

\r\n", + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "//引入 SqlServer 的 NuGet 包\n", + "#r \"nuget:Microsoft.DotNet.Interactive.SqlServer,*-*\"" + ] + }, + { + "cell_type": "markdown", + "id": "e4fc5e3f", + "metadata": {}, + "source": [ + "### 第二步:使用 #!connect 命令的语法,连接数据库子内核" + ] + }, + { + "cell_type": "markdown", + "id": "dc09ad65", + "metadata": {}, + "source": [ + "使用魔术命令 `#!connect mssql --kernel-name SqlServerKernelDemo \"Server=.\\SQL2019;Database=study;User Id=sa;Password=gly-bicijinlian;TrustServerCertificate=true;\"`\n", + "\n", + "实测有缺点:\n", + "+ 不能重复执行:重复执行会报错\n", + "+ 连接字符串必须是真实字符串:不能是变量,不灵活;明文\"不安全\",比如演示环境\n", + "\n", + "变通用法:在C#程序中,拼接好魔术命令`#!connect`,再发送给内核执行" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "201f6662", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Kernel added: #!sql-SqlServerKernelDemo" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "// 连接魔术命令:\n", + "// #!connect mssql --kernel-name SqlServerKernelDemo \"Server=.\\SQL2019;Database=study;User Id=sa;Password=密码;TrustServerCertificate=true;\"\n", + "\n", + "//优化用法\n", + "{\n", + " //内核名:魔法命令中的内核名,执行后会自动加 sql- 前缀,做为内核名被使用\n", + " string magicCommandKernelName = \"SqlServerKernelDemo\";\n", + " string completeKernelName = \"sql-\" + magicCommandKernelName;\n", + "\n", + " //引入内核:可重复执行\n", + " if(Microsoft.DotNet.Interactive.Kernel.Root.FindKernelByName(completeKernelName) == null)\n", + " {\n", + " var connectKernelCode = $\"#!connect mssql --kernel-name {magicCommandKernelName} \\\"{SharedDbConnect.MsSqlConnectionString}\\\"\";\n", + " await Kernel.Root.SendAsync(new SubmitCode( connectKernelCode, \"csharp\"));\n", + " }\n", + " else\n", + " {\n", + " Console.WriteLine($\"名为 {completeKernelName} 的内核已存在。需要新内核时,请为--kernel-name参数使用不同的值, 本次执行不做任何更改!\");\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "9dbc4af6", + "metadata": {}, + "source": [ + "## 查询数据库(SQL Server 2019为例)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "c6474c18", + "metadata": { + "polyglot_notebook": { + "kernelName": "sql-SqlServerKernelDemo" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "命令已成功完成。" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "(10 行受到影响)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/csv": [ + "Id,Name,Age\r\n", + "1,吕宇宁,74\r\n", + "2,韦子异,3\r\n", + "3,姚宇宁,27\r\n", + "4,傅子异,18\r\n", + "5,朱子韬,5\r\n", + "6,林杰宏,73\r\n", + "7,胡璐,60\r\n", + "8,周璐,23\r\n", + "9,田秀英,6\r\n", + "10,姜詩涵,82\r\n" + ], + "text/html": [ + "
IdNameAge
1
吕宇宁
74
2
韦子异
3
3
姚宇宁
27
4
傅子异
18
5
朱子韬
5
6
林杰宏
73
7
胡璐
60
8
周璐
23
9
田秀英
6
10
姜詩涵
82
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "--语句选择 #!connect 命令设置的SQL内核名\n", + "#!sql-SqlServerKernelDemo\n", + "\n", + "--原始SQL查询语句\n", + "select top 10 * from student" + ] + }, + { + "cell_type": "markdown", + "id": "1cc77bdf", + "metadata": {}, + "source": [ + "使用SQL语法,进行数据库操作" + ] + }, + { + "cell_type": "markdown", + "id": "867b43cc", + "metadata": {}, + "source": [ + "## 共享数据库操作结果数据(仅支持SQL Server数据库,以SQL Server 2019为例)" + ] + }, + { + "cell_type": "markdown", + "id": "b1ca8234", + "metadata": {}, + "source": [ + "### 1、引入NuGet包(引入一次就好,为明确步骤再次引入)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.DotNet.Interactive.SqlServer, 1.0.0-beta.25177.1
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#r \"nuget:Microsoft.DotNet.Interactive.SqlServer,*-*\"" + ] + }, + { + "cell_type": "markdown", + "id": "a05705ab", + "metadata": {}, + "source": [ + "### 2、连接内核命令:生成新SQL内核" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Kernel added: #!sql-SqlServerKernelShared" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "//优化变通方式\n", + "{\n", + " //内核名:魔法命令中的内核名,执行后会自动加 sql- 前缀,做为内核名被使用\n", + " string magicCommandKernelName = \"SqlServerKernelShared\";\n", + " string completeKernelName = \"sql-\" + magicCommandKernelName;\n", + "\n", + " //引入内核:可重复执行\n", + " if(Microsoft.DotNet.Interactive.Kernel.Root.FindKernelByName(completeKernelName) == null)\n", + " {\n", + " var connectKernelCode = $\"#!connect mssql --kernel-name {magicCommandKernelName} \\\"{SharedDbConnect.MsSqlConnectionString}\\\"\";\n", + " await Kernel.Root.SendAsync(new SubmitCode( connectKernelCode, \"csharp\"));\n", + " }\n", + " else\n", + " {\n", + " Console.WriteLine($\"名为 {completeKernelName} 的内核已存在。需要新内核时,请为--kernel-name参数使用不同的值, 本次执行不做任何更改!\");\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "cc6a6d60", + "metadata": {}, + "source": [ + "### 3、共享方式使用第2步生成的新SQL内核,操作数据库(使用了 --name 命令参数)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "polyglot_notebook": { + "kernelName": "sql-SqlServerKernelShared" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(5 行受到影响)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "(1 行受到影响)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/csv": [ + "Id,Name,Age\r\n", + "1,吕宇宁,74\r\n", + "2,韦子异,3\r\n", + "3,姚宇宁,27\r\n", + "4,傅子异,18\r\n", + "5,朱子韬,5\r\n" + ], + "text/html": [ + "
IdNameAge
1
吕宇宁
74
2
韦子异
3
3
姚宇宁
27
4
傅子异
18
5
朱子韬
5
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/csv": [ + "Count\r\n", + "5\r\n" + ], + "text/html": [ + "
Count
5
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#!sql-SqlServerKernelShared --name sqlServerKernelQueryShared\n", + "\n", + "SELECT top 5 Id,Name,Age from Student;\n", + "SELECT 5 as Count;" + ] + }, + { + "cell_type": "markdown", + "id": "f4f5988e", + "metadata": {}, + "source": [ + "### 4、多种方式使用查询共享数据" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Id Name Age\n", + "1 吕宇宁 74\n", + "2 韦子异 3\n", + "3 姚宇宁 27\n", + "4 傅子异 18\n", + "5 朱子韬 5\n" + ] + }, + { + "data": { + "text/csv": [ + "Id,Name,Age\r\n", + "1,吕宇宁,74\r\n", + "2,韦子异,3\r\n", + "3,姚宇宁,27\r\n", + "4,傅子异,18\r\n", + "5,朱子韬,5\r\n" + ], + "text/html": [ + "
IdNameAge
1
吕宇宁
74
2
韦子异
3
3
姚宇宁
27
4
傅子异
18
5
朱子韬
5
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/csv": [ + "Count\r\n", + "5\r\n" + ], + "text/html": [ + "
Count
5
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
[{"Id":1,"Name":"吕宇宁","Age":74},{"Id":2,"Name":"韦子异","Age":3},{"Id":3,"Name":"姚宇宁","Age":27},{"Id":4,"Name":"傅子异","Age":18},{"Id":5,"Name":"朱子韬","Age":5}]
{"Id":1,"Name":"吕宇宁","Age":74}
Id
1
Name"吕宇宁"
Age
74
{"Id":2,"Name":"韦子异","Age":3}
Id
2
Name"韦子异"
Age
3
{"Id":3,"Name":"姚宇宁","Age":27}
Id
3
Name"姚宇宁"
Age
27
{"Id":4,"Name":"傅子异","Age":18}
Id
4
Name"傅子异"
Age
18
{"Id":5,"Name":"朱子韬","Age":5}
Id
5
Name"朱子韬"
Age
5
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "//C#语言中使用:查询共享数据\n", + "\n", + "#!set --name fromMsSqlQueryShared --value @sql-SqlServerKernelShared:sqlServerKernelQueryShared\n", + "using Microsoft.DotNet.Interactive.Formatting.TabularData;\n", + "using Microsoft.DotNet.Interactive.Formatting;\n", + "/**\n", + " 说明:这里获取到的共享SQL结果,实质是SQL操作结果的Json序列化字符串;\n", + " 在C#单元格里,默认被反序列化为了 System.Text.Json.JsonElement,其根元素RootElement,是结果集合(几条SQL语句,结果集就有几项)\n", + " .dot interactive程序集中,序列化时,实际是使用 System.Text.Json 序列化的 TabularDataResource 类(在Microsoft.DotNet.Interactive.Formatting.TabularData命名空间)的集合\n", + "\n", + " 所以C#中使用共享数据,有两种方式:直接操作System.Text.Json.JsonElement对象和反序列化为TabularDataResource数组\n", + "*/\n", + "//使用共享数据:直接操作JsonElement对象\n", + "{\n", + " //有几个操作结果,fromMsSqlQuery.RootElement中就有几个结果集\n", + " var dataSet = fromMsSqlQueryShared.RootElement;\n", + "\n", + " //第一个查询结果集\n", + " var dataTable1 = dataSet[0];\n", + "\n", + " //列结构\n", + " var fieldNames = dataTable1.GetProperty(\"schema\").GetProperty(\"fields\").EnumerateArray().Select(s=>s.GetProperty(\"name\"));\n", + "\n", + " Console.WriteLine(string.Join(\" \",fieldNames));\n", + "\n", + " //数据\n", + " var data = dataTable1.GetProperty(\"data\").EnumerateArray().AsEnumerable();\n", + " foreach(var row in data)\n", + " {\n", + " Console.WriteLine($\"{row.GetProperty(\"Id\")} {row.GetProperty(\"Name\")} {row.GetProperty(\"Age\")}\");\n", + " }\n", + "\n", + " //第2个结果集\n", + " var count = fromMsSqlQueryShared.RootElement[1].GetProperty(\"data\")[0].GetProperty(\"Count\");\n", + "\n", + " //优化:使用Html展示\n", + "}\n", + "\n", + "//使用共享数据:反序列化为TabularDataResource数组\n", + "{\n", + " var dataSetJsonText = fromMsSqlQueryShared.RootElement.GetRawText();\n", + " var dataTables = System.Text.Json.JsonSerializer.Deserialize>(dataSetJsonText);\n", + "\n", + " //结果1\n", + " dataTables[0].Display();\n", + " \n", + " //结果2\n", + " dataTables[1].Display();\n", + "}\n", + "\n", + "//使用共享数据:直接转换为TabularDataResource数组\n", + "{\n", + " var resource = fromMsSqlQueryShared.RootElement.ToTabularDataResource().Data.ToList();\n", + " resource[0].First(s => s.Key==\"data\").Value.Display();\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "polyglot_notebook": { + "kernelName": "javascript" + } + }, + "outputs": [ + { + "data": { + "application/json": [ + { + "Age": 74, + "Id": 1, + "Name": "吕宇宁" + }, + { + "Age": 3, + "Id": 2, + "Name": "韦子异" + }, + { + "Age": 27, + "Id": 3, + "Name": "姚宇宁" + }, + { + "Age": 18, + "Id": 4, + "Name": "傅子异" + }, + { + "Age": 5, + "Id": 5, + "Name": "朱子韬" + } + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "//js中使用:查询共享数据\n", + "#!set --name fromMsSqlQueryShared --value @sql-SqlServerKernelShared:sqlServerKernelQueryShared\n", + "console.log(fromMsSqlQueryShared[0].data)" + ] + }, + { + "cell_type": "markdown", + "id": "2c79015c", + "metadata": {}, + "source": [ + "## 各数据库示例" + ] + }, + { + "cell_type": "markdown", + "id": "aacbaafa", + "metadata": {}, + "source": [ + "### SQL Server 数据库" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "180499e7", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.DotNet.Interactive.SqlServer, 1.0.0-beta.25177.1
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#r \"nuget:Microsoft.DotNet.Interactive.SqlServer,*-*\"" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "09172abb", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Kernel added: #!sql-SqlServerKernelStudy" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "using Microsoft.DotNet.Interactive;\n", + "using Microsoft.DotNet.Interactive.Commands;\n", + "\n", + "//优化方式\n", + "{\n", + " //内核名:魔法命令中的内核名,执行后会自动加 sql- 前缀,做为内核名被使用\n", + " string magicCommandKernelName = \"SqlServerKernelStudy\";\n", + " string completeKernelName = \"sql-\" + magicCommandKernelName;\n", + "\n", + " //引入内核:可重复执行\n", + " if(Microsoft.DotNet.Interactive.Kernel.Root.FindKernelByName(completeKernelName) == null)\n", + " {\n", + " var connectKernelCode = $\"#!connect mssql --kernel-name {magicCommandKernelName} \\\"{SharedDbConnect.MsSqlConnectionString}\\\"\";\n", + " await Kernel.Root.SendAsync(new SubmitCode( connectKernelCode, \"csharp\"));\n", + " }\n", + " else\n", + " {\n", + " Console.WriteLine($\"名为 {completeKernelName} 的内核已存在。需要新内核时,请为--kernel-name参数使用不同的值, 本次执行不做任何更改!\");\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "3dac305e", + "metadata": { + "polyglot_notebook": { + "kernelName": "sql-SqlServerKernelStudy" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "命令已成功完成。" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "(5 行受到影响)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/csv": [ + "Id,Name,Age\r\n", + "1,吕宇宁,74\r\n", + "2,韦子异,3\r\n", + "3,姚宇宁,27\r\n", + "4,傅子异,18\r\n", + "5,朱子韬,5\r\n" + ], + "text/html": [ + "
IdNameAge
1
吕宇宁
74
2
韦子异
3
3
姚宇宁
27
4
傅子异
18
5
朱子韬
5
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "--直接执行SQL语句,不共享结果\n", + "#!sql-SqlServerKernelStudy\n", + "SELECT top 5 * from Student;" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "cb3528e0", + "metadata": { + "polyglot_notebook": { + "kernelName": "sql-SqlServerKernelStudy" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "命令已成功完成。" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "(5 行受到影响)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "(1 行受到影响)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/csv": [ + "Id,Name,Age\r\n", + "1,吕宇宁,74\r\n", + "2,韦子异,3\r\n", + "3,姚宇宁,27\r\n", + "4,傅子异,18\r\n", + "5,朱子韬,5\r\n" + ], + "text/html": [ + "
IdNameAge
1
吕宇宁
74
2
韦子异
3
3
姚宇宁
27
4
傅子异
18
5
朱子韬
5
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/csv": [ + "Count\r\n", + "5\r\n" + ], + "text/html": [ + "
Count
5
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "--共享操作结果(可多个操作语句)\n", + "#!sql-SqlServerKernelStudy --name sqlServerQuerySharedDemo\n", + "SELECT top 5 Id,Name,Age from Student;\n", + "SELECT 5 as Count;" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "e41307ed", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Id Name Age\n", + "1 吕宇宁 74\n", + "2 韦子异 3\n", + "3 姚宇宁 27\n", + "4 傅子异 18\n", + "5 朱子韬 5\n" + ] + }, + { + "data": { + "text/csv": [ + "Id,Name,Age\r\n", + "1,吕宇宁,74\r\n", + "2,韦子异,3\r\n", + "3,姚宇宁,27\r\n", + "4,傅子异,18\r\n", + "5,朱子韬,5\r\n" + ], + "text/html": [ + "
IdNameAge
1
吕宇宁
74
2
韦子异
3
3
姚宇宁
27
4
傅子异
18
5
朱子韬
5
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/csv": [ + "Count\r\n", + "5\r\n" + ], + "text/html": [ + "
Count
5
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
[{"Id":1,"Name":"吕宇宁","Age":74},{"Id":2,"Name":"韦子异","Age":3},{"Id":3,"Name":"姚宇宁","Age":27},{"Id":4,"Name":"傅子异","Age":18},{"Id":5,"Name":"朱子韬","Age":5}]
{"Id":1,"Name":"吕宇宁","Age":74}
Id
1
Name"吕宇宁"
Age
74
{"Id":2,"Name":"韦子异","Age":3}
Id
2
Name"韦子异"
Age
3
{"Id":3,"Name":"姚宇宁","Age":27}
Id
3
Name"姚宇宁"
Age
27
{"Id":4,"Name":"傅子异","Age":18}
Id
4
Name"傅子异"
Age
18
{"Id":5,"Name":"朱子韬","Age":5}
Id
5
Name"朱子韬"
Age
5
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#!set --name fromMsSqlQuery --value @sql-SqlServerKernelStudy:sqlServerQuerySharedDemo\n", + "using Microsoft.DotNet.Interactive.Formatting.TabularData;\n", + "using Microsoft.DotNet.Interactive.Formatting;\n", + "/**\n", + " 说明:这里获取到的共享SQL结果,实质是SQL操作结果的Json序列化字符串;\n", + " 在C#单元格里,默认被反序列化为了 System.Text.Json.JsonElement,其根元素RootElement,是结果集合(几条SQL语句,结果集就有几项)\n", + " .dot interactive程序集中,序列化时,实际是使用 System.Text.Json 序列化的 TabularDataResource 类(在Microsoft.DotNet.Interactive.Formatting.TabularData命名空间)的集合\n", + "\n", + " 所以C#中使用共享数据,有两种方式:直接操作System.Text.Json.JsonElement对象和反序列化为TabularDataResource数组\n", + "*/\n", + "//使用共享数据:直接操作JsonElement对象\n", + "{\n", + " //有几个操作结果,fromMsSqlQuery.RootElement中就有几个结果集\n", + " var dataSet = fromMsSqlQuery.RootElement;\n", + "\n", + " //第一个查询结果集\n", + " var dataTable1 = dataSet[0];\n", + "\n", + " //列结构\n", + " var fieldNames = dataTable1.GetProperty(\"schema\").GetProperty(\"fields\").EnumerateArray().Select(s=>s.GetProperty(\"name\"));\n", + "\n", + " Console.WriteLine(string.Join(\" \",fieldNames));\n", + "\n", + " //数据\n", + " var data = dataTable1.GetProperty(\"data\").EnumerateArray().AsEnumerable();\n", + " foreach(var row in data)\n", + " {\n", + " Console.WriteLine($\"{row.GetProperty(\"Id\")} {row.GetProperty(\"Name\")} {row.GetProperty(\"Age\")}\");\n", + " }\n", + "\n", + " //第2个结果集\n", + " var count = fromMsSqlQuery.RootElement[1].GetProperty(\"data\")[0].GetProperty(\"Count\");\n", + "\n", + " //优化:使用Html展示\n", + "}\n", + "\n", + "//使用共享数据:反序列化为TabularDataResource数组\n", + "{\n", + " var dataSetJsonText = fromMsSqlQuery.RootElement.GetRawText();\n", + " var dataTables = System.Text.Json.JsonSerializer.Deserialize>(dataSetJsonText);\n", + "\n", + " //结果1\n", + " dataTables[0].Display();\n", + " \n", + " //结果2\n", + " dataTables[1].Display();\n", + "}\n", + "\n", + "//使用共享数据:直接转换为TabularDataResource数组\n", + "{\n", + " var resource = fromMsSqlQuery.RootElement.ToTabularDataResource().Data.ToList();\n", + " resource[0].First(s => s.Key==\"data\").Value.Display();\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "eabc34b9", + "metadata": { + "polyglot_notebook": { + "kernelName": "javascript" + } + }, + "outputs": [ + { + "data": { + "application/json": [ + { + "Age": 74, + "Id": 1, + "Name": "吕宇宁" + }, + { + "Age": 3, + "Id": 2, + "Name": "韦子异" + }, + { + "Age": 27, + "Id": 3, + "Name": "姚宇宁" + }, + { + "Age": 18, + "Id": 4, + "Name": "傅子异" + }, + { + "Age": 5, + "Id": 5, + "Name": "朱子韬" + } + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#!set --name fromMsSqlQuery --value @sql-SqlServerKernelStudy:sqlServerQuerySharedDemo\n", + "console.log(fromMsSqlQuery[0].data)" + ] + }, + { + "cell_type": "markdown", + "id": "91512503", + "metadata": {}, + "source": [ + "### PostgreSQL 数据库" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "45adfb6a", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.DotNet.Interactive.PostgreSQL, 1.0.0-beta.25177.1
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Loading extension script from `C:\\Users\\ruyu\\.nuget\\packages\\microsoft.dotnet.interactive.postgresql\\1.0.0-beta.25177.1\\interactive-extensions\\dotnet\\extension.dib`" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Query PostgreSQL databases.\r\n", + "

This extension adds support for connecting to PostgreSql databases using the #!connect postgres magic command.

\r\n", + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#r \"nuget:Microsoft.DotNet.Interactive.PostgreSQL,*-*\"" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "3d0496c9", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Kernel added: #!sql-PostgreSQLStudy" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "//魔术命令\n", + "//#!connect postgres --kernel-name PostgreSQLStudy \"Host=localhost;Port=5432;Username=postgres;Password=替换成真实密码;Database=Study;\"\n", + "\n", + "using Microsoft.DotNet.Interactive;\n", + "using Microsoft.DotNet.Interactive.Commands;\n", + "\n", + "//优化方法\n", + "{\n", + " //内核名:魔法命令中的内核名,执行后会自动加 sql- 前缀,做为内核名被使用\n", + " string magicCommandKernelName = \"PostgreSQLStudy\";\n", + " string completeKernelName = \"sql-\" + magicCommandKernelName;\n", + "\n", + " //引入内核:可重复执行\n", + " if(Microsoft.DotNet.Interactive.Kernel.Root.FindKernelByName(completeKernelName) == null)\n", + " {\n", + " var connectKernelCode = $\"#!connect postgres --kernel-name {magicCommandKernelName} \\\"{SharedDbConnect.PSQLConnectionString}\\\"\";\n", + " await Kernel.Root.SendAsync(new SubmitCode( connectKernelCode, \"csharp\"));\n", + " }\n", + " else\n", + " {\n", + " Console.WriteLine($\"名为 {completeKernelName} 的内核已存在。需要新内核时,请为--kernel-name参数使用不同的值, 本次执行不做任何更改!\");\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "df085375", + "metadata": { + "polyglot_notebook": { + "kernelName": "sql-PostgreSQLStudy" + } + }, + "outputs": [ + { + "data": { + "text/csv": [ + "Id,Name,Age\r\n", + "1,邵致远,62\r\n", + "2,孙致远,4\r\n" + ], + "text/html": [ + "
IdNameAge
1
邵致远
62
2
孙致远
4
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/csv": [ + "count\r\n", + "1000\r\n" + ], + "text/html": [ + "
count
1000
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#!sql-PostgreSQLStudy\n", + "SELECT * FROM \"Student\" LIMIT 2;\n", + "SELECT COUNT(*) as Count FROM \"Student\";" + ] + }, + { + "cell_type": "markdown", + "id": "ff349c06", + "metadata": {}, + "source": [ + "### SQLite 数据库" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "b37177b2", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.DotNet.Interactive.SQLite, 1.0.0-beta.25177.1
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Loading extension script from `C:\\Users\\ruyu\\.nuget\\packages\\microsoft.dotnet.interactive.sqlite\\1.0.0-beta.25177.1\\interactive-extensions\\dotnet\\extension.dib`" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Query SQLite databases.\r\n", + "

This extension adds support for connecting to SQLite databases using the #!connect sqlite magic command. For more information, run a cell using the #!sql magic command.

\r\n", + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#r \"nuget:Microsoft.DotNet.Interactive.SQLite,*-*\"" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "57b043ec", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Kernel added: #!sql-SQLiteSharedKernel" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "/* 各种连接参数\n", + "\n", + " 相对位置:当前目录\n", + " #!connect sqlite --kernel-name SQLiteSharedKernel --connection-string \"Data Source=.\\assets\\database\\study.db;\"\n", + "\n", + " 绝对目录位置\n", + " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=C:\\Database\\SQLiteDemo.db;\"\n", + " \n", + " 缓存共享\n", + " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=.\\assets\\database\\study.db;Cache=Shared;\"\n", + "\n", + " 使用带密码\n", + " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=.\\assets\\database\\study.db;Cache=Shared;Password=MyEncryptionKey;\"\n", + " \n", + " 只读模式\n", + " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=.\\assets\\database\\study.db;Mode=ReadOnly\"\n", + "\n", + " 读写创建模式\n", + " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=.\\assets\\database\\study.db;Mode=ReadWriteCreate\"\n", + "\n", + " 读写模式\n", + " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=.\\assets\\database\\study.db;Mode=ReadWrite\"\n", + "\n", + " 私有内存模式\n", + " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=:memory:\"\n", + "\n", + " 共享内存模式\n", + " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=Sharable;Mode=Memory;Cache=Shared\"\n", + "*/\n", + "\n", + "using Microsoft.DotNet.Interactive;\n", + "using Microsoft.DotNet.Interactive.Commands;\n", + "//优化方法\n", + "{\n", + " //内核名:魔法命令中的内核名,执行后会自动加 sql- 前缀,做为内核名被使用\n", + " string magicCommandKernelName = \"SQLiteSharedKernel\";\n", + " string completeKernelName = \"sql-\" + magicCommandKernelName;\n", + "\n", + " //引入内核:可重复执行\n", + " if(Microsoft.DotNet.Interactive.Kernel.Root.FindKernelByName(completeKernelName) == null)\n", + " {\n", + " var connectKernelCode = $\"#!connect sqlite --kernel-name {magicCommandKernelName} --connection-string \\\"{SharedDbConnect.SQLiteConnectionString}\\\"\";\n", + " await Kernel.Root.SendAsync(new SubmitCode( connectKernelCode, \"csharp\"));\n", + " }\n", + " else\n", + " {\n", + " Console.WriteLine($\"名为 {completeKernelName} 的内核已存在。需要新内核时,请为--kernel-name参数使用不同的值, 本次执行不做任何更改!\");\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "76d8d37f", + "metadata": { + "polyglot_notebook": { + "kernelName": "sql-SQLiteSharedKernel" + } + }, + "outputs": [ + { + "data": { + "text/csv": [ + "Id,Name,Age\r\n", + "1,龚致远,70\r\n", + "2,潘宇宁,48\r\n" + ], + "text/html": [ + "
IdNameAge
1
龚致远
70
2
潘宇宁
48
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/csv": [ + "Count\r\n", + "1000\r\n" + ], + "text/html": [ + "
Count
1000
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#!sql-SQLiteSharedKernel\n", + "SELECT * FROM Student LIMIT 2;\n", + "SELECT COUNT(*) AS Count FROM Student;" + ] + }, + { + "cell_type": "markdown", + "id": "eccfd5c5", + "metadata": {}, + "source": [ + "### DuckDB 数据库" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "5ee11d91", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.DotNet.Interactive.DuckDB, 1.0.0-beta.25177.1
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Loading extension script from `C:\\Users\\ruyu\\.nuget\\packages\\microsoft.dotnet.interactive.duckdb\\1.0.0-beta.25177.1\\interactive-extensions\\dotnet\\extension.dib`" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Query DuckDB databases.\r\n", + "

This extension adds support for connecting to DuckDB databases using the #!connect duckdb magic command.

\r\n", + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#r \"nuget:Microsoft.DotNet.Interactive.DuckDB,*-*\"" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "52a0668c", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Kernel added: #!DuckDBSharedKernel" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/csv": [ + "\r\n" + ], + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "//下面这种被注释的方式:不可重复执行\n", + "// #!connect duckdb --kernel-name DuckDBSharedKernel --connection-string \"Data Source=:memory:?cache=shared\"\n", + "// #!connect duckdb --kernel-name DuckDBSharedKernel --connection-string SharedDbConnect.DuckDBConnectionString\n", + "\n", + "using Microsoft.DotNet.Interactive;\n", + "using Microsoft.DotNet.Interactive.Commands;\n", + "//优化方法\n", + "{\n", + " //内核名:魔法命令中的内核名,执行后会不加 sql- 前缀\n", + " string magicCommandKernelName = \"DuckDBSharedKernel\";\n", + "\n", + " //引入内核:可重复执行\n", + " if(Kernel.Root.FindKernelByName(magicCommandKernelName) == null)\n", + " {\n", + " var connectKernelCode = $\"#!connect duckdb --kernel-name {magicCommandKernelName} --connection-string \\\"{SharedDbConnect.DuckDBConnectionString}\\\"\";\n", + " await Kernel.Root.SendAsync(new SubmitCode( connectKernelCode, \"csharp\"));\n", + "\n", + " //初始化数据表及填充数据\n", + " var connectKernelCode2 = \n", + " \"\"\"\n", + " #!DuckDBSharedKernel\n", + " CREATE TABLE Student (\n", + " Id INTEGER,\n", + " Name TEXT,\n", + " Age INTEGER\n", + " );\n", + " INSERT INTO Student VALUES (1, '张三', 10), (2, '李四', 33), (3, '王五', 66);\n", + " \"\"\";\n", + " await Kernel.Root.SendAsync(new SubmitCode( connectKernelCode2, \"csharp\"));\n", + " }\n", + " else\n", + " {\n", + " Console.WriteLine($\"名为 {magicCommandKernelName} 的内核已存在。需要新内核时,请为--kernel-name参数使用不同的值, 本次执行不做任何更改!\");\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "7afddc24", + "metadata": { + "polyglot_notebook": { + "kernelName": "DuckDBSharedKernel" + } + }, + "outputs": [ + { + "data": { + "text/csv": [ + "Id,Name,Age\r\n", + "1,张三,10\r\n", + "2,李四,33\r\n", + "3,王五,66\r\n" + ], + "text/html": [ + "
IdNameAge
1
张三
10
2
李四
33
3
王五
66
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#!DuckDBSharedKernel\n", + "SELECT * FROM Student ORDER BY Id" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "language_info": { + "name": "polyglot-notebook" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "languageName": "csharp", + "name": "csharp" + }, + { + "aliases": [], + "languageName": "KQL", + "name": "DuckDBSharedKernel" + }, + { + "aliases": [], + "languageName": "T-SQL", + "name": "sql-mssql-study" + }, + { + "aliases": [], + "languageName": "T-SQL", + "name": "sql-mssqlDemo" + }, + { + "aliases": [], + "languageName": "PostgreSQL", + "name": "sql-PostgreSQLStudy" + }, + { + "aliases": [], + "languageName": "SQLite", + "name": "sql-SQLiteSharedKernel" + }, + { + "aliases": [], + "languageName": "T-SQL", + "name": "sql-SqlServerKernelDemo" + }, + { + "aliases": [], + "languageName": "T-SQL", + "name": "sql-SqlServerKernelShared" + }, + { + "aliases": [], + "languageName": "T-SQL", + "name": "sql-SqlServerKernelStudy" + }, + { + "aliases": [], + "languageName": "T-SQL", + "name": "sql-SqlServerKernelStuidy" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Docs/多语言笔记.2.1.连接数据库.ipynb b/Docs/多语言笔记.2.1.连接数据库.ipynb index a955fd8..1658cfc 100644 --- a/Docs/多语言笔记.2.1.连接数据库.ipynb +++ b/Docs/多语言笔记.2.1.连接数据库.ipynb @@ -38,7 +38,8 @@ }, "outputs": [], "source": [ - "#r \"nuget:Microsoft.Dotnet.Interactive.SqlServer,*-*\"" + "#r \"nuget:Microsoft.Dotnet.Interactive.SqlServer,*-*\"\n", + "#r \"nuget:Microsoft.Identity.Client,4.66.2\"" ] }, { @@ -302,24 +303,6 @@ "var c = context.Database.ExecuteSql(fs);\n", "display(c);" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "sql-DemoEF" - }, - "polyglot_notebook": { - "kernelName": "sql-DemoEF" - } - }, - "outputs": [], - "source": [ - "#!sql-DemoEF\n", - "\n", - "var data = from " - ] } ], "metadata": { diff --git a/Docs/多语言笔记.2.2.操作数据库-C#.ipynb b/Docs/多语言笔记.2.2.操作数据库-C#.ipynb new file mode 100644 index 0000000..dc2463d --- /dev/null +++ b/Docs/多语言笔记.2.2.操作数据库-C#.ipynb @@ -0,0 +1,1048 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "19839fa7", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "使用 .net 程序操作数据库\n", + "=======================\n", + "除了使用SQL内核执行SQL语句直接操作数据库,使用最多的是使用用.net程序操作数据库:\n", + "+ ado.net 原生操作\n", + "+ 使用ORM框架,比如 Daper、EFCore、SqlSugar、FreeSQL等" + ] + }, + { + "cell_type": "markdown", + "id": "4ca948bd", + "metadata": {}, + "source": [ + "## 初始化" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "4f5767d2", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Dapper, 2.1.66
  • DuckDB.NET.Data.Full, 1.2.1
  • Microsoft.Data.SqlClient, 6.0.1
  • Microsoft.Data.Sqlite, 9.0.4
  • Microsoft.EntityFrameworkCore, 9.0.4
  • Microsoft.EntityFrameworkCore.Sqlite, 9.0.4
  • Microsoft.EntityFrameworkCore.SqlServer, 9.0.4
  • MongoDB.EntityFrameworkCore, 9.0.0
  • MySql.Data, 9.3.0
  • MySql.EntityFrameworkCore, 9.0.3
  • Npgsql, 9.0.3
  • Npgsql.EntityFrameworkCore.PostgreSQL, 9.0.4
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.Extensions.Configuration, 9.0.4
  • Microsoft.Extensions.Configuration.Binder, 9.0.4
  • Microsoft.Extensions.Configuration.CommandLine, 9.0.4
  • Microsoft.Extensions.Configuration.EnvironmentVariables, 9.0.4
  • Microsoft.Extensions.Configuration.ini, 9.0.4
  • Microsoft.Extensions.Configuration.json, 9.0.4
  • Microsoft.Extensions.Configuration.KeyPerFile, 9.0.4
  • Microsoft.Extensions.Configuration.UserSecrets, 9.0.4
  • Microsoft.Extensions.Configuration.xml, 9.0.4
  • microsoft.extensions.dependencyinjection, 9.0.4
  • microsoft.extensions.logging, 9.0.4
  • Microsoft.Extensions.Logging.Configuration, 9.0.4
  • Microsoft.Extensions.Logging.Console, 9.0.4
  • Microsoft.Extensions.Logging.Debug, 9.0.4
  • Microsoft.Extensions.Logging.EventSource, 9.0.4
  • microsoft.extensions.options, 9.0.4
  • Microsoft.Extensions.Options.ConfigurationExtensions, 9.0.4
  • Microsoft.Extensions.Options.DataAnnotations, 9.0.4
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#!import \"./Base.ipynb\"\n", + "\n", + "//共享\n", + "#r \"nuget:Microsoft.Data.SqlClient\"\n", + "#r \"nuget:MySql.Data\"\n", + "#r \"nuget:Npgsql\"\n", + "#r \"nuget:Microsoft.Data.Sqlite\"\n", + "#r \"nuget:DuckDB.NET.Data.Full\"\n", + "\n", + "#r \"nuget:Dapper\"\n", + "\n", + "#r \"nuget:Microsoft.EntityFrameworkCore\"\n", + "#r \"nuget:Microsoft.EntityFrameworkCore.SqlServer\"\n", + "#r \"nuget:Microsoft.EntityFrameworkCore.Sqlite\"\n", + "#r \"nuget:Npgsql.EntityFrameworkCore.PostgreSQL\"\n", + "#r \"nuget:MySql.EntityFrameworkCore\"\n", + "//#r \"nuget:Pomelo.EntityFrameworkCore.MySql\"\n", + "#r \"nuget:MongoDB.EntityFrameworkCore\"\n", + "\n", + "global using System.Text.Json;\n", + "global using System.Text.Json.Schema;\n", + "global using System.Text.Json.Serialization;\n", + "\n", + "global using System.Data;\n", + "global using System.Data.Common;\n", + "global using System.Data.SqlTypes;\n", + "global using System.Data.SqlClient;\n", + "//global using System.Data.OracleClient;\n", + "\n", + "global using Microsoft.Data.SqlClient;\n", + "global using Microsoft.Data.SqlClient.Server;\n", + "\n", + "global using MySql.Data;\n", + "global using MySql.Data.Types;\n", + "global using MySql.Data.MySqlClient;\n", + "\n", + "global using Microsoft.Data.Sqlite;\n", + "\n", + "global using DuckDB.NET.Data;\n", + "global using DuckDB.NET.Data.DataChunk;\n", + "\n", + "global using Dapper;\n", + "\n", + "global using Npgsql;\n", + "global using Npgsql.Schema;\n", + "global using Npgsql.PostgresTypes;\n", + "global using Npgsql.TypeMapping;\n", + "global using Npgsql.Util;\n", + "global using Npgsql.NameTranslation;\n", + "global using Npgsql.BackendMessages;\n", + "\n", + "\n", + "global using Microsoft.EntityFrameworkCore;\n", + "global using Microsoft.EntityFrameworkCore.SqlServer;\n", + "global using Microsoft.EntityFrameworkCore.Sqlite;\n", + "global using Npgsql.EntityFrameworkCore.PostgreSQL;\n", + "global using MySql.EntityFrameworkCore;\n", + "global using MongoDB.EntityFrameworkCore;\n", + "\n", + "//共享方法\n", + "public static List DatatableToStudent(DataTable studentTable)\n", + "{\n", + " var students = new List();\n", + " if(studentTable == null)\n", + " {\n", + " return students;\n", + " }\n", + "\n", + " if(studentTable.Columns.Count ==0)\n", + " {\n", + " return students;\n", + " }\n", + "\n", + " if(studentTable.Rows.Count <=0)\n", + " {\n", + " return students;\n", + " }\n", + "\n", + " foreach(DataRow row in studentTable.Rows)\n", + " {\n", + " var student = new Student()\n", + " {\n", + " Id = (int)row[\"Id\"],\n", + " Name = row[\"Name\"] == DBNull.Value ? \"\" : (string)row[\"Name\"].ToString(),\n", + " Age = row[\"Age\"] == DBNull.Value ? 0 : (int)row[\"Age\"]\n", + " };\n", + "\n", + " students.Add(student);\n", + " }\n", + "\n", + " return students;\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "c66c5da7", + "metadata": {}, + "source": [ + "## 使用 ADO.NET" + ] + }, + { + "cell_type": "markdown", + "id": "6b1ebc4f", + "metadata": {}, + "source": [ + "### SQL Server 数据库(2019为例)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f64d17d8", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "查询到: 528 行数据\n", + "前2行:[{\"Id\":1,\"Name\":\"吕宇宁\",\"Age\":74},{\"Id\":6,\"Name\":\"林杰宏\",\"Age\":73}]\n" + ] + } + ], + "source": [ + "//Ado.Net 操作SQL Server\n", + "{\n", + " DataSet ds = new DataSet();\n", + "\n", + " using(var mssqlConnection = new SqlConnection(SharedDbConnect.MsSqlConnectionString))\n", + " {\n", + " mssqlConnection.Open();\n", + "\n", + " var querySql = \"select * FROM student where age >@age;\";\n", + " SqlParameter[] parameters = new SqlParameter[]\n", + " {\n", + " new SqlParameter()\n", + " {\n", + " ParameterName = \"age\",\n", + " SqlDbType = SqlDbType.Int,\n", + " Value = 50,\n", + " Direction = ParameterDirection.Input,\n", + " Size = 4,\n", + " DbType = DbType.Int32,\n", + " IsNullable = false,\n", + " }\n", + " };\n", + " var command = new SqlCommand(querySql, mssqlConnection);\n", + " command.Parameters.AddRange(parameters);\n", + "\n", + " var adapter = new SqlDataAdapter(command);\n", + " adapter.Fill(ds);\n", + "\n", + " mssqlConnection.Close();\n", + " mssqlConnection.Dispose();\n", + " }\n", + "\n", + " var students = DatatableToStudent(ds.Tables[0]);\n", + "\n", + " Console.WriteLine($\"查询到: {students.Count()} 行数据\");\n", + " var jsonText = System.Text.Json.JsonSerializer.Serialize(students.Take(2), new System.Text.Json.JsonSerializerOptions()\n", + " {\n", + " Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All),\n", + " WriteIndented = false,\n", + " });\n", + "\n", + " Console.WriteLine($\"前2行:{jsonText}\");\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "a604fbea", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "source": [ + "### MySQL" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "90085b98", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Id Name Age \n", + "1 江子韬 28 \n", + "2 苏震南 48 \n" + ] + } + ], + "source": [ + "//Ado.Net 操作MySQL\n", + "{\n", + " //查询数据\n", + " DataSet ds = new DataSet();\n", + "\n", + " using(var sqlConnection = new MySqlConnection(SharedDbConnect.MySQLConnectionString))\n", + " {\n", + " sqlConnection.Open();\n", + "\n", + " var querySql = \"SELECT * FROM `Student` LIMIT 2;\";\n", + " var command = new MySqlCommand(querySql, sqlConnection);\n", + "\n", + " var adapter = new MySqlDataAdapter(command);\n", + " adapter.Fill(ds);\n", + "\n", + " sqlConnection.Close();\n", + " sqlConnection.Dispose();\n", + " }\n", + "\n", + " //输出数据\n", + " var dt = ds.Tables[0];\n", + " int padRightCount = 15;\n", + "\n", + " //输出列\n", + " List columnNames = new List(100);\n", + " foreach(DataColumn c in dt.Columns)\n", + " {\n", + " columnNames.Add(c.ColumnName.PadRight(padRightCount));\n", + " }\n", + "\n", + " Console.WriteLine(string.Join(\"\", columnNames));\n", + "\n", + " //输出数据\n", + " foreach(DataRow row in dt.Rows)\n", + " {\n", + " List rowItemValues = new List(100);\n", + "\n", + " for(int i=0; i columnNames = new List(100);\n", + " foreach(DataColumn c in dt.Columns)\n", + " {\n", + " columnNames.Add(c.ColumnName.PadRight(padRightCount));\n", + " }\n", + "\n", + " Console.WriteLine(string.Join(\"\", columnNames));\n", + "\n", + " //输出数据\n", + " foreach(DataRow row in dt.Rows)\n", + " {\n", + " List rowItemValues = new List(100);\n", + "\n", + " for(int i=0; i columnNames = reader.GetColumnSchema().Select(c => c.ColumnName.PadRight(padRightCount)).ToList();\n", + " Console.WriteLine(string.Join(\"\", columnNames));\n", + "\n", + " //循环输出行数据\n", + " while (await reader.ReadAsync())\n", + " {\n", + " List rowItemValues = new List(100);\n", + " for(int i=0; i(i).ToString();\n", + " rowItemValues.Add(valueText.PadRight(padRightCount));\n", + " }\n", + "\n", + " Console.WriteLine(string.Join(\"\",rowItemValues));\n", + " }\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "e1c9381b", + "metadata": {}, + "source": [ + "### SQLite" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "96de0cac", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Id Name Age \n", + "1 龚致远 70 \n", + "2 潘宇宁 48 \n", + "3 陶杰宏 5 \n", + "4 彭晓明 46 \n", + "5 江震南 63 \n" + ] + } + ], + "source": [ + "//Ado.Net 操作SQLite\n", + "{\n", + " //查询数据\n", + " DataSet ds = new DataSet();\n", + " int padRightCount = 15;\n", + "\n", + " using(var sqlConnection = new SqliteConnection(SharedDbConnect.SQLiteConnectionString))\n", + " {\n", + " sqlConnection.Open();\n", + " \n", + " var querySql = \n", + " \"\"\"\n", + " SELECT * FROM Student LIMIT 5;\n", + " \"\"\";\n", + " var cmd = sqlConnection.CreateCommand();\n", + " cmd.CommandType = CommandType.Text;\n", + " cmd.CommandText = querySql;\n", + "\n", + " using (var reader = await cmd.ExecuteReaderAsync())\n", + " {\n", + " //输出列名\n", + " List columnNames = reader.GetColumnSchema().Select(c => c.ColumnName.PadRight(padRightCount)).ToList();\n", + " Console.WriteLine(string.Join(\"\", columnNames));\n", + "\n", + " //循环输出行数据\n", + " while (await reader.ReadAsync())\n", + " {\n", + " List rowItemValues = new List(100);\n", + " for(int i=0; i(i).ToString();\n", + " rowItemValues.Add(valueText.PadRight(padRightCount));\n", + " }\n", + "\n", + " Console.WriteLine(string.Join(\"\",rowItemValues));\n", + " }\n", + " }\n", + "\n", + " sqlConnection.Close();\n", + " sqlConnection.Dispose();\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "b0035452", + "metadata": {}, + "source": [ + "### DuckDB" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "f986fed7", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Id Name Age \n", + "1 张三 10 \n", + "2 李四 33 \n", + "3 王五 66 \n" + ] + } + ], + "source": [ + "//Ado.Net 操作DuckDB数据库\n", + "{\n", + " int padRightCount = 15;\n", + "\n", + " using(var sqlConnection = new DuckDBConnection(SharedDbConnect.DuckDBConnectionString))\n", + " {\n", + " sqlConnection.Open();\n", + " //1、创建表\n", + " var createTableSql = \n", + " \"\"\"\n", + " CREATE TABLE Student \n", + " (\n", + " Id INTEGER,\n", + " Name TEXT,\n", + " Age INTEGER\n", + " );\n", + " \"\"\";\n", + "\n", + " var createCommand = sqlConnection.CreateCommand();\n", + " createCommand.CommandType = CommandType.Text;\n", + " createCommand.CommandText = createTableSql;\n", + "\n", + " var createCount = createCommand.ExecuteNonQuery();\n", + " //Console.WriteLine($\"{createCount}\");\n", + "\n", + " //2、插入示例数据\n", + " var insertSql = \n", + " \"\"\"\n", + " INSERT INTO Student VALUES (1, '张三', 10), (2, '李四', 33), (3, '王五', 66);\n", + " \"\"\";\n", + "\n", + " var insertCommand = sqlConnection.CreateCommand();\n", + " insertCommand.CommandType = CommandType.Text;\n", + " insertCommand.CommandText = insertSql;\n", + "\n", + " var insertCount = insertCommand.ExecuteNonQuery();\n", + " //Console.WriteLine($\"{insertCount}\");\n", + "\n", + " //3、查询数据\n", + " var querySql = \n", + " \"\"\"\n", + " SELECT * FROM Student ORDER BY Age\n", + " \"\"\";\n", + " var queryCommand = sqlConnection.CreateCommand();\n", + " queryCommand.CommandType = CommandType.Text;\n", + " queryCommand.CommandText = querySql;\n", + "\n", + " using (var reader = await queryCommand.ExecuteReaderAsync())\n", + " {\n", + " //输出列名\n", + " List columnNames = reader.GetColumnSchema().Select(c => c.ColumnName.PadRight(padRightCount)).ToList();\n", + " Console.WriteLine(string.Join(\"\", columnNames));\n", + "\n", + " //循环输出行数据\n", + " while (await reader.ReadAsync())\n", + " {\n", + " List rowItemValues = new List(100);\n", + " for(int i=0; i(querySql).Take(2);\n", + " var jsonText = System.Text.Json.JsonSerializer.Serialize(students, new System.Text.Json.JsonSerializerOptions()\n", + " {\n", + " Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All),\n", + " WriteIndented = false,\n", + " });\n", + "\n", + " Console.WriteLine(jsonText);\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "d5daa579", + "metadata": {}, + "source": [ + "### Dapper 操作 MySQL" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "0cd87012", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{\"Id\":1,\"Name\":\"江子韬\",\"Age\":28},{\"Id\":2,\"Name\":\"苏震南\",\"Age\":48}]\r\n" + ] + } + ], + "source": [ + "//Dapper 操作MySQL\n", + "{\n", + " using(var dbConnection = new MySqlConnection(SharedDbConnect.MySQLConnectionString))\n", + " {\n", + " var querySql = \"SELECT * FROM `Student` LIMIT @top;\";\n", + " var students = dbConnection.Query(querySql, new {top=2});\n", + "\n", + " var jsonText = System.Text.Json.JsonSerializer.Serialize(students, new System.Text.Json.JsonSerializerOptions()\n", + " {\n", + " Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All),\n", + " WriteIndented = false,\n", + " });\n", + "\n", + " Console.WriteLine(jsonText);\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "bac2b8e0", + "metadata": {}, + "source": [ + "### Dapper 操作 PostgreSQL" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "7a476608", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{\"Id\":1,\"Name\":\"邵致远\",\"Age\":62},{\"Id\":3,\"Name\":\"陶震南\",\"Age\":60}]\r\n" + ] + } + ], + "source": [ + "//Dapper 操作 PSQL\n", + "{\n", + " using(var dbConnection = new NpgsqlConnection(SharedDbConnect.PSQLConnectionString))\n", + " {\n", + " var querySql = \"SELECT * FROM \\\"Student\\\" Where \\\"Age\\\" > @Age LIMIT @Top;\";\n", + " var students = dbConnection.Query(querySql, new {Age = 50, top = 2});\n", + "\n", + " var jsonText = System.Text.Json.JsonSerializer.Serialize(students, new System.Text.Json.JsonSerializerOptions()\n", + " {\n", + " Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All),\n", + " WriteIndented = false,\n", + " });\n", + "\n", + " Console.WriteLine(jsonText);\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "9075b64b", + "metadata": {}, + "source": [ + "## 使用 EF Core" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "047da44c", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "//共享\n", + "/// \n", + "/// SQL Server DbContext\n", + "/// \n", + "public class StudyDbContext: DbContext\n", + "{\n", + " public StudyDbContext(DbContextOptions option):base(option)\n", + " {\n", + "\n", + " }\n", + "\n", + " public DbSet Student {get; set;}\n", + "\n", + " protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n", + " {\n", + " base.OnConfiguring(optionsBuilder);\n", + " if(!optionsBuilder.IsConfigured)\n", + " {\n", + " Console.WriteLine(\"没有设置\");\n", + " }\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "3c61973d", + "metadata": {}, + "source": [ + "### EF Core 操作 SQL Server\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "6da513fd", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
indexvalue
0
Submission#17+Student
Id
33
Name
戴嘉伦
Age
99
1
Submission#17+Student
Id
45
Name
曾震南
Age
98
2
Submission#17+Student
Id
55
Name
丁子韬
Age
96
3
Submission#17+Student
Id
65
Name
冯宇宁
Age
99
4
Submission#17+Student
Id
167
Name
严睿
Age
96
5
Submission#17+Student
Id
199
Name
孔秀英
Age
96
6
Submission#17+Student
Id
232
Name
王睿
Age
99
7
Submission#17+Student
Id
305
Name
董子异
Age
99
8
Submission#17+Student
Id
318
Name
许晓明
Age
97
9
Submission#17+Student
Id
329
Name
孟宇宁
Age
99
10
Submission#17+Student
Id
338
Name
陶秀英
Age
99
11
Submission#17+Student
Id
382
Name
袁云熙
Age
99
12
Submission#17+Student
Id
400
Name
戴安琪
Age
96
13
Submission#17+Student
Id
413
Name
尹詩涵
Age
99
14
Submission#17+Student
Id
436
Name
罗岚
Age
96
15
Submission#17+Student
Id
439
Name
陆岚
Age
97
16
Submission#17+Student
Id
444
Name
戴璐
Age
97
17
Submission#17+Student
Id
457
Name
谢岚
Age
99
18
Submission#17+Student
Id
477
Name
卢杰宏
Age
97
19
Submission#17+Student
Id
482
Name
萧杰宏
Age
100
(23 more)
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "{ //EF Core SQL Server\n", + " var builder = new DbContextOptionsBuilder();\n", + " builder.UseSqlServer(SharedDbConnect.MsSqlConnectionString);\n", + "\n", + " var dbContext = new StudyDbContext(builder.Options);\n", + " var students = dbContext.Student.Where(s => s.Age> 95).ToList();\n", + " students.Display();\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "c4b85b82", + "metadata": {}, + "source": [ + "### EF Core 查询 MySQL" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "9d5dc22b", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
indexvalue
0
Submission#17+Student
Id
26
Name
邱璐
Age
98
1
Submission#17+Student
Id
58
Name
曾致远
Age
97
2
Submission#17+Student
Id
59
Name
苏秀英
Age
96
3
Submission#17+Student
Id
80
Name
廖詩涵
Age
97
4
Submission#17+Student
Id
99
Name
顾岚
Age
98
5
Submission#17+Student
Id
148
Name
金震南
Age
99
6
Submission#17+Student
Id
172
Name
武秀英
Age
96
7
Submission#17+Student
Id
246
Name
金云熙
Age
99
8
Submission#17+Student
Id
268
Name
董秀英
Age
96
9
Submission#17+Student
Id
281
Name
梁震南
Age
98
10
Submission#17+Student
Id
313
Name
阎子异
Age
97
11
Submission#17+Student
Id
321
Name
顾嘉伦
Age
96
12
Submission#17+Student
Id
329
Name
钟子韬
Age
96
13
Submission#17+Student
Id
378
Name
叶璐
Age
96
14
Submission#17+Student
Id
394
Name
邹致远
Age
96
15
Submission#17+Student
Id
436
Name
李子异
Age
99
16
Submission#17+Student
Id
480
Name
马晓明
Age
97
17
Submission#17+Student
Id
482
Name
贺睿
Age
96
18
Submission#17+Student
Id
484
Name
朱嘉伦
Age
98
19
Submission#17+Student
Id
548
Name
龚震南
Age
96
(27 more)
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "{ //EF Core MySQL\n", + " var builder = new DbContextOptionsBuilder();\n", + " builder.UseMySQL(SharedDbConnect.MySQLConnectionString);\n", + "\n", + " var dbContext = new StudyDbContext(builder.Options);\n", + " var students = dbContext.Student.Where(s => s.Age> 95).ToList();\n", + " students.Display();\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "81d3e14d", + "metadata": {}, + "source": [ + "### EFCore PostgreSQL" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "42dd5655", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
indexvalue
0
Submission#17+Student
Id
11
Name
张子异
Age
98
1
Submission#17+Student
Id
19
Name
范璐
Age
96
2
Submission#17+Student
Id
51
Name
贾震南
Age
99
3
Submission#17+Student
Id
54
Name
董子异
Age
99
4
Submission#17+Student
Id
60
Name
张安琪
Age
98
5
Submission#17+Student
Id
81
Name
郭震南
Age
99
6
Submission#17+Student
Id
86
Name
罗璐
Age
97
7
Submission#17+Student
Id
94
Name
贺睿
Age
97
8
Submission#17+Student
Id
100
Name
钱睿
Age
97
9
Submission#17+Student
Id
164
Name
苏睿
Age
97
10
Submission#17+Student
Id
211
Name
杜睿
Age
98
11
Submission#17+Student
Id
238
Name
孔詩涵
Age
98
12
Submission#17+Student
Id
263
Name
贾子韬
Age
97
13
Submission#17+Student
Id
310
Name
毛震南
Age
96
14
Submission#17+Student
Id
322
Name
方宇宁
Age
97
15
Submission#17+Student
Id
357
Name
尹晓明
Age
99
16
Submission#17+Student
Id
380
Name
张震南
Age
97
17
Submission#17+Student
Id
434
Name
徐子异
Age
99
18
Submission#17+Student
Id
468
Name
姚子异
Age
96
19
Submission#17+Student
Id
524
Name
顾璐
Age
98
(18 more)
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "{ \n", + " var builder = new DbContextOptionsBuilder();\n", + " builder.UseNpgsql(SharedDbConnect.PSQLConnectionString);\n", + "\n", + " var dbContext = new StudyDbContext(builder.Options);\n", + " var students = dbContext.Student.Where(s => s.Age> 95).ToList();\n", + " students.Display();\n", + "}" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "languageName": "csharp", + "name": "csharp" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Docs/多语言笔记.2.2.连接SQLite.ipynb b/Docs/多语言笔记.2.2.连接SQLite.ipynb deleted file mode 100644 index aadb143..0000000 --- a/Docs/多语言笔记.2.2.连接SQLite.ipynb +++ /dev/null @@ -1,268 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "连接到 SQLite 数据库\n", - "============================== " - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "连接到 SQLite 数据库,并操作数据。注意:此功能在 Microsoft.DotNet.Interactive.ExtensionLab 扩展库中,要先引用 Nuget 包。" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 设置Nuget包源" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "outputs": [], - "source": [ - "#i \"https://api.nuget.org/v3/index.json\"" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 引用 Nuget 包" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "outputs": [], - "source": [ - "#r \"nuget: Microsoft.DotNet.Interactive.ExtensionLab,*-*\"" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 连接到 SQLite 数据库" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "引用扩展库后,使用 #!connect sqlite 命令连接到SQLite数据库!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "outputs": [], - "source": [ - "#!connect sqlite --kernel-name MySQLiteDemo \"Data Source=sqlite\\\\SQLiteDemo.db\"\n", - "\n", - "/*\n", - " 相对目录位置\n", - " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=Database\\SQLiteDemo.db;\"\n", - " \n", - " 缓存共享\n", - " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=Database\\SQLiteDemo.db;Cache=Shared;\"\n", - "\n", - " 使用带密码\n", - " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=SQLiteDemo.db;Cache=Shared;Password=MyEncryptionKey;\"\n", - " \n", - " 只读模式\n", - " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=SQLiteDemo.db;Mode=ReadOnly\"\n", - "\n", - " 读写创建模式\n", - " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=SQLiteDemo.db;Mode=ReadWriteCreate\"\n", - "\n", - " 读写模式\n", - " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=SQLiteDemo.db;Mode=ReadWrite\"\n", - "\n", - " 私有内存模式\n", - " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=:memory:\"\n", - "\n", - " 共享内存模式\n", - " #!connect sqlite --kernel-name MySQLiteDemo \"Data Source=Sharable;Mode=Memory;Cache=Shared\"\n", - "*/" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 使用连接操作数据库" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "sql-MySQLiteDemo" - }, - "polyglot_notebook": { - "kernelName": "sql-MySQLiteDemo" - } - }, - "outputs": [], - "source": [ - "#!sql-MySQLiteDemo\n", - "\n", - "select * from person;" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## C#中使用" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - } - }, - "outputs": [], - "source": [ - "//直接引用包,使用类库操作就可以了,不需要使用 上下文连接" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".NET (C#)", - "language": "C#", - "name": ".net-csharp" - }, - "language_info": { - "name": "polyglot-notebook" - }, - "polyglot_notebook": { - "kernelInfo": { - "defaultKernelName": "csharp", - "items": [ - { - "aliases": [], - "name": ".NET" - }, - { - "aliases": [ - "C#", - "c#" - ], - "languageName": "C#", - "name": "csharp" - }, - { - "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": [], - "languageName": "SQL", - "name": "sql" - }, - { - "aliases": [], - "languageName": "T-SQL", - "name": "sql-Demo" - }, - { - "aliases": [], - "languageName": "T-SQL", - "name": "sql-DemoEF" - }, - { - "aliases": [], - "languageName": "SQLite", - "name": "sql-MySQLiteDemo" - }, - { - "aliases": [], - "name": "value" - }, - { - "aliases": [ - "frontend" - ], - "name": "vscode" - } - ] - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/Docs/练习-Html-PocketView.ipynb b/Docs/练习-Html-PocketView.ipynb new file mode 100644 index 0000000..6aa5f91 --- /dev/null +++ b/Docs/练习-Html-PocketView.ipynb @@ -0,0 +1,304 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fdfbe9e1", + "metadata": {}, + "source": [ + "使用PocketView,操作Html\n", + "=======================" + ] + }, + { + "cell_type": "markdown", + "id": "a17a651c", + "metadata": {}, + "source": [ + "PocketView是一个API,用于使用C#代码,用HTML的术语简明地编写HTML。就像HTML方法一样,它返回一个实现IHtmlCent的对象,因此输出将被假定为有效的HTML并呈现到您的笔记本中。这里有一个例子:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5859c1f7", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "using Microsoft.DotNet.Interactive.Formatting;\n", + "using static Microsoft.DotNet.Interactive.Formatting.PocketViewTags;\n", + "\n", + "PocketView pocketView = PocketViewTags.span(img[src:\"https://www.baidu.com/img/flexible/logo/pc/result.png\",style:\"height:1em\"],HTML(\" \"), a[href:@\"https://www.baidu.com\"](i(\"百度\")));\n", + "pocketView.Display();\n", + "\n", + "//display(pocketView);" + ] + }, + { + "cell_type": "markdown", + "id": "ed5a269f", + "metadata": {}, + "source": [ + "解析上面的代码:\n", + "+ 调用span方法:传递三个参数,img方法结果、HTML方法结果、a方法结果;\n", + "+ img方法是通过一个索引器调用的,该索引器传递了几个命名参数,src和style; \n", + "+ HTML方法有一个字符串参数 ` ` 即空格的 html 转义字符;\n", + "+ a方法有另一个索引器参数(href)和一个参数,在本例中是对i方法的调用;\n", + "\n", + "实质:以C#对象的方式,组装了一段 html代码片断" + ] + }, + { + "cell_type": "markdown", + "id": "8d862b6e", + "metadata": {}, + "source": [ + "通过将PocketView转换为字符串,您可以看到它产生的实际HTML,该字符串将以纯文本而不是HTML显示" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "//display(pocketView.ToDisplayString());\n", + "display(pocketView.ToString());" + ] + }, + { + "cell_type": "markdown", + "id": "9ef8c896", + "metadata": {}, + "source": [ + "由于HTML难以使用静态类型语言进行简洁表示,PocketView采用了动态类型。这使得你可以使用任意索引器名称来指定HTML属性。PocketViewTags上的每个方法都返回一个动态的PocketView。让我们更详细地了解你可以用PocketView实现的功能。\n", + "\n", + "注意:在本节的代码示例中,通过在笔记本中运行`using static Microsoft.DotNet.Interactive.Formatting.PocketViewTags`,你可以直接调用PocketView方法,而无需类名限定。\n", + "\n", + "如上所述,你可以使用方括号限定符来指定HTML属性,小括号填充HTML元素内容:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "//span html片断\n", + "PocketView spanElement = span[style:\"font-style:italic\"](\"你好,我带了倾斜样式\");\n", + "spanElement.Display();\n", + "\n", + "//图片 html片断\n", + "PocketView imgElement = img[src:\"https://www.baidu.com/img/flexible/logo/pc/result.png\",style:\"height:1em\", title:\"百度图片\"];\n", + "imgElement.Display();\n", + "\n", + "//超级连接 html片断\n", + "PocketView linkElement = a[href:@\"https://www.baidu.com\"](i(\"百度连接\"));\n", + "linkElement.Display();" + ] + }, + { + "cell_type": "markdown", + "id": "8fe067db", + "metadata": {}, + "source": [ + "如果你将一个字符串传递给PocketView,它会为你进行HTML编码:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "//sapn本身作为html标签,被当作Html显示;但span里的html样式的内容不被当作html渲染,而是编码后直接显示\n", + "PocketView view = span(\"
对我 进行编码
\");\n", + "//原样显示html片断自身,不作为html元素进行渲染\n", + "display(view);\n", + "\n", + "//显示被html编码过的原始字符串\n", + "display(view.ToString());" + ] + }, + { + "cell_type": "markdown", + "id": "2376610d", + "metadata": {}, + "source": [ + "这就是HTML方法派上用场的地方。如果你想将一个字符串传递给PocketView,但又不希望它被HTML编码,你可以简单地将该字符串用HTML方法包裹起来:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "//HTML方法后,就作为 html片断进行 \"渲染\" 了\n", + "PocketView view2 = span(HTML(\"
Don't encode me!
\"));\n", + "display(view2);\n", + "display(view2.ToString());" + ] + }, + { + "cell_type": "markdown", + "id": "bd47366d", + "metadata": {}, + "source": [ + "HTML简单地将一个字符串捕获到一个实现IHtmlContent接口的实例中。该接口用于指示该值不应被HTML编码,而是应被视为有效的HTML并直接呈现。\n", + "\n", + "了解了这一点,可能不会感到惊讶的是,PocketView本身也实现了IHtmlContent接口。\n", + "\n", + "你还可以将其他类型的对象传递给PocketView。当你这样做时,它们会使用纯文本格式化器进行格式化,该格式化器默认会扩展对象的属性。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "PocketView view3 = b(\n", + " new {Fruit=\"apple\", Texture=\"smooth\"}\n", + ");\n", + "\n", + "display(view3)" + ] + }, + { + "cell_type": "markdown", + "id": "b7c66e90", + "metadata": {}, + "source": [ + "由于目前.NET Interactive的格式化API不支持为嵌套的HTML片段生成格式化器,PocketView会回退到text/plain格式化器来描述传递对象的属性。\n", + "\n", + "你也可以将对象列表传递给PocketView。这对于从数据生成HTML非常有用:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "var fruits = new []{\"apple\",\"banana\",\"cherry\"};\n", + "var colors = new []{\"green\",\"#F1C40F\",\"red\"};\n", + "\n", + "\n", + "ul(\n", + " fruits.Zip(colors).Select(x => li[style:$\"color:{x.Item2}\"](x.Item1))\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "cc60cd12", + "metadata": {}, + "source": [ + "总结:其实这样的方式 \"组装\"html页面或片断,会非常繁琐;只适合临时做一些简单的html组装;\n", + "方案:\n", + "+ 使用 html 内核: 但有个最大问题是\"html内核不能使用共享数据\";只适合纯静态页面;\n", + "+ 使用 javascript 内核: 虽然能使用 \"共享数据\"功能,但js内核长处是操作现有html并非生成html;\n", + "+ 使用 razor 或 blazor 库,像razor或blazor页面或组件一样,就非常方便了;`非常推荐的终极解决方案` 唯一缺点是智能提示差,可以在VS里写好,粘贴过来哈;" + ] + }, + { + "cell_type": "markdown", + "id": "20446659", + "metadata": {}, + "source": [ + "使用 Razor的例子:体验下方不方便(后面专题讲解)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "#r \"nuget:RazorInteractive\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "polyglot_notebook": { + "kernelName": "razor" + } + }, + "outputs": [], + "source": [ + "#!razor\n", + "@{\n", + " \n", + " var dic = new Dictionary()\n", + " {\n", + " {\"apple\",\"green\"},\n", + " {\"banana\",\"#F1C40F\"},\n", + " {\"cherry\",\"red\"},\n", + " };\n", + "}\n", + "\n", + "
    \n", + " @foreach(var item in dic)\n", + " {\n", + "
  • @item.Key
  • ;\n", + " }\n", + "
" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "languageName": "csharp", + "name": "csharp" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Docs/练习-添加Jupyter内核.ipynb b/Docs/练习-添加Jupyter内核.ipynb new file mode 100644 index 0000000..8b0129b --- /dev/null +++ b/Docs/练习-添加Jupyter内核.ipynb @@ -0,0 +1,131 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a59722d6", + "metadata": {}, + "source": [ + "Polyglot Netebooks 中,添加Jupyter内核,支持Python语言\n", + "====================================================" + ] + }, + { + "cell_type": "markdown", + "id": "23bcd178", + "metadata": {}, + "source": [ + "使用魔术命令 \n", + "\n", + "无Conda环境:`#!connect jupyter --kernel-name pythonkernel --kernel-spec python3`\n", + "有Conda环境:`#!connect jupyter --kernel-name pythonkernel --conda-env base --kernel-spec python3`\n", + "\n", + "实测有缺点:\n", + "+ 不能重复执行:重复执行会报错\n", + "+ 连接字符串必须是真实字符串:不能是变量,不灵活;明文\"不安全\",比如演示环境\n", + "\n", + "变通用法:在C#程序中,拼接好魔术命令`#!connect`,再发送给内核执行" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b10341c4", + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "名为 Pythonkernel 的内核已存在。需要新内核时,请为--kernel-name参数使用不同的值, 本次执行不做任何更改!\r\n" + ] + } + ], + "source": [ + "//魔术命令\n", + "// #!connect jupyter --kernel-name pythonkernel --kernel-spec python3\n", + "// #!connect jupyter --kernel-name pythonkernel --conda-env base --kernel-spec python3\n", + "\n", + "using Microsoft.DotNet.Interactive;\n", + "using Microsoft.DotNet.Interactive.Commands;\n", + "\n", + "//优化方式\n", + "{\n", + " //内核名:\n", + " string magicCommandKernelName = \"Pythonkernel\";\n", + "\n", + " //引入内核:可重复执行\n", + " if(Microsoft.DotNet.Interactive.Kernel.Root.FindKernelByName(magicCommandKernelName) == null)\n", + " {\n", + " var connectKernelCode = $\"#!connect jupyter --kernel-name {magicCommandKernelName} --kernel-spec python3\";\n", + " await Kernel.Root.SendAsync(new SubmitCode( connectKernelCode, \"csharp\"));\n", + " }\n", + " else\n", + " {\n", + " Console.WriteLine($\"名为 {magicCommandKernelName} 的内核已存在。需要新内核时,请为--kernel-name参数使用不同的值, 本次执行不做任何更改!\");\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "polyglot_notebook": { + "kernelName": "pythonkernel" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "hello,python3!\n" + ] + } + ], + "source": [ + "#!Pythonkernel\n", + "# 写 python 代码\n", + "print(\"hello,python3!\");" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "language_info": { + "name": "polyglot-notebook" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "languageName": "csharp", + "name": "csharp" + }, + { + "aliases": [], + "languageName": "python", + "name": "pythonkernel" + }, + { + "aliases": [], + "languageName": "python", + "name": "Pythonkernel" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}