diff --git a/Docs/assets/images/PocketView.jpg b/Docs/assets/images/PocketView.jpg new file mode 100644 index 0000000..3ae3e9f Binary files /dev/null and b/Docs/assets/images/PocketView.jpg differ diff --git a/Docs/assets/images/操作数据库-C#.jpg b/Docs/assets/images/操作数据库-C#.jpg new file mode 100644 index 0000000..1ba672c Binary files /dev/null and b/Docs/assets/images/操作数据库-C#.jpg differ diff --git a/Docs/多语言笔记.1.2.PocketView渲染html.md b/Docs/多语言笔记.1.2.PocketView渲染html.md new file mode 100644 index 0000000..ecc7c74 --- /dev/null +++ b/Docs/多语言笔记.1.2.PocketView渲染html.md @@ -0,0 +1,111 @@ +使用PocketView,操作Html +======================= +PocketView是一个API,用于使用C#代码,用HTML的术语简明地编写HTML。就像HTML方法一样,它返回一个实现IHtmlCent的对象,因此输出将被假定为有效的HTML并呈现到您的笔记本中。这里有一个例子: +```csharp +using Microsoft.DotNet.Interactive.Formatting; +using static Microsoft.DotNet.Interactive.Formatting.PocketViewTags; + +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("百度"))); +pocketView.Display(); + +//display(pocketView); +``` +解析上面的代码: ++ 调用span方法:传递三个参数,img方法结果、HTML方法结果、a方法结果; ++ img方法是通过一个索引器调用的,该索引器传递了几个命名参数,src和style; ++ HTML方法有一个字符串参数 ` ` 即空格的 html 转义字符; ++ a方法有另一个索引器参数(href)和一个参数,在本例中是对i方法的调用; + +实质:以C#对象的方式,组装了一段 html代码片断 +通过将PocketView转换为字符串,您可以看到它产生的实际HTML,该字符串将以纯文本而不是HTML显示 +```csharp +//display(pocketView.ToDisplayString()); +display(pocketView.ToString()); +``` +由于HTML难以使用静态类型语言进行简洁表示,PocketView采用了动态类型。这使得你可以使用任意索引器名称来指定HTML属性。PocketViewTags上的每个方法都返回一个动态的PocketView。让我们更详细地了解你可以用PocketView实现的功能。 + +注意:在本节的代码示例中,通过在笔记本中运行`using static Microsoft.DotNet.Interactive.Formatting.PocketViewTags`,你可以直接调用PocketView方法,而无需类名限定。 + +如上所述,你可以使用方括号限定符来指定HTML属性,小括号填充HTML元素内容: +```csharp +//span html片断 +PocketView spanElement = span[style:"font-style:italic"]("你好,我带了倾斜样式"); +spanElement.Display(); + +//图片 html片断 +PocketView imgElement = img[src:"https://www.baidu.com/img/flexible/logo/pc/result.png",style:"height:1em", title:"百度图片"]; +imgElement.Display(); + +//超级连接 html片断 +PocketView linkElement = a[href:@"https://www.baidu.com"](i("百度连接")); +linkElement.Display(); +``` +如果你将一个字符串传递给PocketView,它会为你进行HTML编码: +```csharp +//sapn本身作为html标签,被当作Html显示;但span里的html样式的内容不被当作html渲染,而是编码后直接显示 +PocketView view = span("
对我 进行编码
"); +//原样显示html片断自身,不作为html元素进行渲染 +display(view); + +//显示被html编码过的原始字符串 +display(view.ToString()); +``` +这就是HTML方法派上用场的地方。如果你想将一个字符串传递给PocketView,但又不希望它被HTML编码,你可以简单地将该字符串用HTML方法包裹起来: +```csharp +//HTML方法后,就作为 html片断进行 "渲染" 了 +PocketView view2 = span(HTML("
Don't encode me!
")); +display(view2); +display(view2.ToString()); +``` +HTML简单地将一个字符串捕获到一个实现IHtmlContent接口的实例中。该接口用于指示该值不应被HTML编码,而是应被视为有效的HTML并直接呈现。 + +了解了这一点,可能不会感到惊讶的是,PocketView本身也实现了IHtmlContent接口。 + +你还可以将其他类型的对象传递给PocketView。当你这样做时,它们会使用纯文本格式化器进行格式化,该格式化器默认会扩展对象的属性。 +```csharp +PocketView view3 = b( + new {Fruit="apple", Texture="smooth"} +); + +display(view3) +``` +由于目前.NET Interactive的格式化API不支持为嵌套的HTML片段生成格式化器,PocketView会回退到text/plain格式化器来描述传递对象的属性。 + +你也可以将对象列表传递给PocketView。这对于从数据生成HTML非常有用: +```csharp +var fruits = new []{"apple","banana","cherry"}; +var colors = new []{"green","#F1C40F","red"}; + + +ul( + fruits.Zip(colors).Select(x => li[style:$"color:{x.Item2}"](x.Item1)) +) +``` +总结:其实这样的方式 "组装"html页面或片断,会非常繁琐;只适合临时做一些简单的html组装; +方案: ++ 使用 html 内核: 但有个最大问题是"html内核不能使用共享数据";只适合纯静态页面; ++ 使用 javascript 内核: 虽然能使用 "共享数据"功能,但js内核长处是操作现有html并非生成html; ++ 使用 razor 或 blazor 库,像razor或blazor页面或组件一样,就非常方便了;`非常推荐的终极解决方案` 唯一缺点是智能提示差,可以在VS里写好,粘贴过来哈; +使用 Razor的例子:体验下方不方便(后面专题讲解) +```csharp +#r "nuget:RazorInteractive" +``` +```razor +#!razor +@{ + + var dic = new Dictionary() + { + {"apple","green"}, + {"banana","#F1C40F"}, + {"cherry","red"}, + }; +} + + +``` diff --git a/Docs/多语言笔记.2.2.操作数据库-C#.md b/Docs/多语言笔记.2.2.操作数据库-C#.md new file mode 100644 index 0000000..1c2a0f4 --- /dev/null +++ b/Docs/多语言笔记.2.2.操作数据库-C#.md @@ -0,0 +1,514 @@ +使用 .net 程序操作数据库 +======================= +除了使用SQL内核执行SQL语句直接操作数据库,使用最多的是使用用.net程序操作数据库: ++ ado.net 原生操作 ++ 使用ORM框架,比如 Daper、EFCore、SqlSugar、FreeSQL等 +## 初始化 +```csharp +#!import "./Base.ipynb" + +//共享 +#r "nuget:Microsoft.Data.SqlClient" +#r "nuget:MySql.Data" +#r "nuget:Npgsql" +#r "nuget:Microsoft.Data.Sqlite" +#r "nuget:DuckDB.NET.Data.Full" + +#r "nuget:Dapper" + +#r "nuget:Microsoft.EntityFrameworkCore" +#r "nuget:Microsoft.EntityFrameworkCore.SqlServer" +#r "nuget:Microsoft.EntityFrameworkCore.Sqlite" +#r "nuget:Npgsql.EntityFrameworkCore.PostgreSQL" +#r "nuget:MySql.EntityFrameworkCore" +//#r "nuget:Pomelo.EntityFrameworkCore.MySql" +#r "nuget:MongoDB.EntityFrameworkCore" + +global using System.Text.Json; +global using System.Text.Json.Schema; +global using System.Text.Json.Serialization; + +global using System.Data; +global using System.Data.Common; +global using System.Data.SqlTypes; +global using System.Data.SqlClient; +//global using System.Data.OracleClient; + +global using Microsoft.Data.SqlClient; +global using Microsoft.Data.SqlClient.Server; + +global using MySql.Data; +global using MySql.Data.Types; +global using MySql.Data.MySqlClient; + +global using Microsoft.Data.Sqlite; + +global using DuckDB.NET.Data; +global using DuckDB.NET.Data.DataChunk; + +global using Dapper; + +global using Npgsql; +global using Npgsql.Schema; +global using Npgsql.PostgresTypes; +global using Npgsql.TypeMapping; +global using Npgsql.Util; +global using Npgsql.NameTranslation; +global using Npgsql.BackendMessages; + + +global using Microsoft.EntityFrameworkCore; +global using Microsoft.EntityFrameworkCore.SqlServer; +global using Microsoft.EntityFrameworkCore.Sqlite; +global using Npgsql.EntityFrameworkCore.PostgreSQL; +global using MySql.EntityFrameworkCore; +global using MongoDB.EntityFrameworkCore; + +//共享方法 +public static List DatatableToStudent(DataTable studentTable) +{ + var students = new List(); + if(studentTable == null) + { + return students; + } + + if(studentTable.Columns.Count ==0) + { + return students; + } + + if(studentTable.Rows.Count <=0) + { + return students; + } + + foreach(DataRow row in studentTable.Rows) + { + var student = new Student() + { + Id = (int)row["Id"], + Name = row["Name"] == DBNull.Value ? "" : (string)row["Name"].ToString(), + Age = row["Age"] == DBNull.Value ? 0 : (int)row["Age"] + }; + + students.Add(student); + } + + return students; +} +``` +## 使用 ADO.NET +### SQL Server 数据库(2019为例) +```csharp +//Ado.Net 操作SQL Server +{ + DataSet ds = new DataSet(); + + using(var mssqlConnection = new SqlConnection(SharedDbConnect.MsSqlConnectionString)) + { + mssqlConnection.Open(); + + var querySql = "select * FROM student where age >@age;"; + SqlParameter[] parameters = new SqlParameter[] + { + new SqlParameter() + { + ParameterName = "age", + SqlDbType = SqlDbType.Int, + Value = 50, + Direction = ParameterDirection.Input, + Size = 4, + DbType = DbType.Int32, + IsNullable = false, + } + }; + var command = new SqlCommand(querySql, mssqlConnection); + command.Parameters.AddRange(parameters); + + var adapter = new SqlDataAdapter(command); + adapter.Fill(ds); + + mssqlConnection.Close(); + mssqlConnection.Dispose(); + } + + var students = DatatableToStudent(ds.Tables[0]); + + Console.WriteLine($"查询到: {students.Count()} 行数据"); + var jsonText = System.Text.Json.JsonSerializer.Serialize(students.Take(2), new System.Text.Json.JsonSerializerOptions() + { + Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All), + WriteIndented = false, + }); + + Console.WriteLine($"前2行:{jsonText}"); +} +``` +### MySQL +```csharp +//Ado.Net 操作MySQL +{ + //查询数据 + DataSet ds = new DataSet(); + + using(var sqlConnection = new MySqlConnection(SharedDbConnect.MySQLConnectionString)) + { + sqlConnection.Open(); + + var querySql = "SELECT * FROM `Student` LIMIT 2;"; + var command = new MySqlCommand(querySql, sqlConnection); + + var adapter = new MySqlDataAdapter(command); + adapter.Fill(ds); + + sqlConnection.Close(); + sqlConnection.Dispose(); + } + + //输出数据 + var dt = ds.Tables[0]; + int padRightCount = 15; + + //输出列 + List columnNames = new List(100); + foreach(DataColumn c in dt.Columns) + { + columnNames.Add(c.ColumnName.PadRight(padRightCount)); + } + + Console.WriteLine(string.Join("", columnNames)); + + //输出数据 + foreach(DataRow row in dt.Rows) + { + List rowItemValues = new List(100); + + for(int i=0; i columnNames = new List(100); + foreach(DataColumn c in dt.Columns) + { + columnNames.Add(c.ColumnName.PadRight(padRightCount)); + } + + Console.WriteLine(string.Join("", columnNames)); + + //输出数据 + foreach(DataRow row in dt.Rows) + { + List rowItemValues = new List(100); + + for(int i=0; i columnNames = reader.GetColumnSchema().Select(c => c.ColumnName.PadRight(padRightCount)).ToList(); + Console.WriteLine(string.Join("", columnNames)); + + //循环输出行数据 + while (await reader.ReadAsync()) + { + List rowItemValues = new List(100); + for(int i=0; i(i).ToString(); + rowItemValues.Add(valueText.PadRight(padRightCount)); + } + + Console.WriteLine(string.Join("",rowItemValues)); + } + } +} +``` +### SQLite +```csharp +//Ado.Net 操作SQLite +{ + //查询数据 + DataSet ds = new DataSet(); + int padRightCount = 15; + + using(var sqlConnection = new SqliteConnection(SharedDbConnect.SQLiteConnectionString)) + { + sqlConnection.Open(); + + var querySql = + """ + SELECT * FROM Student LIMIT 5; + """; + var cmd = sqlConnection.CreateCommand(); + cmd.CommandType = CommandType.Text; + cmd.CommandText = querySql; + + using (var reader = await cmd.ExecuteReaderAsync()) + { + //输出列名 + List columnNames = reader.GetColumnSchema().Select(c => c.ColumnName.PadRight(padRightCount)).ToList(); + Console.WriteLine(string.Join("", columnNames)); + + //循环输出行数据 + while (await reader.ReadAsync()) + { + List rowItemValues = new List(100); + for(int i=0; i(i).ToString(); + rowItemValues.Add(valueText.PadRight(padRightCount)); + } + + Console.WriteLine(string.Join("",rowItemValues)); + } + } + + sqlConnection.Close(); + sqlConnection.Dispose(); + } +} +``` +### DuckDB +```csharp +//Ado.Net 操作DuckDB数据库 +{ + int padRightCount = 15; + + using(var sqlConnection = new DuckDBConnection(SharedDbConnect.DuckDBConnectionString)) + { + sqlConnection.Open(); + //1、创建表 + var createTableSql = + """ + CREATE TABLE Student + ( + Id INTEGER, + Name TEXT, + Age INTEGER + ); + """; + + var createCommand = sqlConnection.CreateCommand(); + createCommand.CommandType = CommandType.Text; + createCommand.CommandText = createTableSql; + + var createCount = createCommand.ExecuteNonQuery(); + //Console.WriteLine($"{createCount}"); + + //2、插入示例数据 + var insertSql = + """ + INSERT INTO Student VALUES (1, '张三', 10), (2, '李四', 33), (3, '王五', 66); + """; + + var insertCommand = sqlConnection.CreateCommand(); + insertCommand.CommandType = CommandType.Text; + insertCommand.CommandText = insertSql; + + var insertCount = insertCommand.ExecuteNonQuery(); + //Console.WriteLine($"{insertCount}"); + + //3、查询数据 + var querySql = + """ + SELECT * FROM Student ORDER BY Age + """; + var queryCommand = sqlConnection.CreateCommand(); + queryCommand.CommandType = CommandType.Text; + queryCommand.CommandText = querySql; + + using (var reader = await queryCommand.ExecuteReaderAsync()) + { + //输出列名 + List columnNames = reader.GetColumnSchema().Select(c => c.ColumnName.PadRight(padRightCount)).ToList(); + Console.WriteLine(string.Join("", columnNames)); + + //循环输出行数据 + while (await reader.ReadAsync()) + { + List rowItemValues = new List(100); + for(int i=0; i(querySql).Take(2); + var jsonText = System.Text.Json.JsonSerializer.Serialize(students, new System.Text.Json.JsonSerializerOptions() + { + Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All), + WriteIndented = false, + }); + + Console.WriteLine(jsonText); + } +} +``` +### Dapper 操作 MySQL +```csharp +//Dapper 操作MySQL +{ + using(var dbConnection = new MySqlConnection(SharedDbConnect.MySQLConnectionString)) + { + var querySql = "SELECT * FROM `Student` LIMIT @top;"; + var students = dbConnection.Query(querySql, new {top=2}); + + var jsonText = System.Text.Json.JsonSerializer.Serialize(students, new System.Text.Json.JsonSerializerOptions() + { + Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All), + WriteIndented = false, + }); + + Console.WriteLine(jsonText); + } +} +``` +### Dapper 操作 PostgreSQL +```csharp +//Dapper 操作 PSQL +{ + using(var dbConnection = new NpgsqlConnection(SharedDbConnect.PSQLConnectionString)) + { + var querySql = "SELECT * FROM \"Student\" Where \"Age\" > @Age LIMIT @Top;"; + var students = dbConnection.Query(querySql, new {Age = 50, top = 2}); + + var jsonText = System.Text.Json.JsonSerializer.Serialize(students, new System.Text.Json.JsonSerializerOptions() + { + Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All), + WriteIndented = false, + }); + + Console.WriteLine(jsonText); + } +} +``` +## 使用 EF Core +```csharp +//共享 +/// +/// SQL Server DbContext +/// +public class StudyDbContext: DbContext +{ + public StudyDbContext(DbContextOptions option):base(option) + { + + } + + public DbSet Student {get; set;} + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + base.OnConfiguring(optionsBuilder); + if(!optionsBuilder.IsConfigured) + { + Console.WriteLine("没有设置"); + } + } +} +``` +### EF Core 操作 SQL Server + +```csharp +{ //EF Core SQL Server + var builder = new DbContextOptionsBuilder(); + builder.UseSqlServer(SharedDbConnect.MsSqlConnectionString); + + var dbContext = new StudyDbContext(builder.Options); + var students = dbContext.Student.Where(s => s.Age> 95).ToList(); + students.Display(); +} +``` +### EF Core 查询 MySQL +```csharp +{ //EF Core MySQL + var builder = new DbContextOptionsBuilder(); + builder.UseMySQL(SharedDbConnect.MySQLConnectionString); + + var dbContext = new StudyDbContext(builder.Options); + var students = dbContext.Student.Where(s => s.Age> 95).ToList(); + students.Display(); +} +``` +### EFCore PostgreSQL +```csharp +{ + var builder = new DbContextOptionsBuilder(); + builder.UseNpgsql(SharedDbConnect.PSQLConnectionString); + + var dbContext = new StudyDbContext(builder.Options); + var students = dbContext.Student.Where(s => s.Age> 95).ToList(); + students.Display(); +} +```