隨筆20250721 PostgreSQL實體類生成器

我來幫你創建一個C#程序,從PostgreSQL數據庫讀取表結構并生成對應的實體類文件。我已經創建了一個完整的PostgreSQL實體類生成器。這個程序包含以下主要功能:

主要特性

  1. 數據庫連接: 使用Npgsql連接PostgreSQL數據庫
  2. 表結構讀取: 自動讀取所有表的結構信息
  3. 類型映射: 將PostgreSQL數據類型映射為C#數據類型
  4. 實體生成: 為每個表生成對應的C#實體類
  5. 文件導出: 將生成的類保存到指定文件夾

使用方法

  1. 安裝NuGet包:

    Install-Package Npgsql
    
  2. 配置連接字符串: 修改Main方法中的連接字符串:

    var connectionString = "Host=localhost;Database=your_database;Username=your_username;Password=your_password;";
    
  3. 設置輸出路徑:

    var outputPath = @"C:\GeneratedEntities";
    
  4. 運行程序: 執行后會自動生成所有表的實體類

生成的實體類特點

  • 包含完整的Data Annotations特性
  • 主鍵字段標記為[Key]
  • 字段映射使用[Column]特性
  • 支持可空類型
  • 字符串長度限制
  • 帕斯卡命名法(下劃線轉換)

支持的數據類型

  • 整數類型:int, long, short
  • 浮點類型:float, double, decimal
  • 文本類型:string
  • 日期時間:DateTime, DateTimeOffset, TimeSpan
  • 其他:bool, Guid, byte[]

生成的實體類可以直接用于Entity Framework Core或其他ORM框架。

1.try cath 寫在哪里? 寫在 ViewModel層 Servace層最多使用自定義異常業務異常進行處理(傳給ViewModel層處理), DAO層進行數據庫操作流水賬式,但是要做好資源釋放操作
2.DbHelp 是什么模式?單例?釋放需要手動釋放?單例模式(和項目的整個聲明周期一起,關了就完蛋了),不需要關閉(和項目的整個聲明周期一起,關了就完蛋了),無法批量插入是因為 表結構還沒完全構建完成,解決方法,先插入第一條來“預熱”連接,如果還有后續的數據,就直接進行批量插入.public async Task InitTestOrdersAsync(){await _db.DeleteTableAsync<Orders>();await _db.CreateTableAsync<Orders>();var mockOrders = new List<Orders>();// ... (生成 mockOrders 的代碼) ...if (mockOrders.Any()){// 1. 先插入第一條來“預熱”連接await _db.InsertAsync(mockOrders.First());// 2. 再批量插入剩下的數據var remainingOrders = mockOrders.Skip(1).ToList();if(remainingOrders.Any()){await _db.InsertAllAsync(remainingOrders);}}}3.弄清 異步和非異步方法的區別,以及使用場景
只要底層(DAO 和 HttpClient)是異步的,Service 層 和 ViewModel 層也都必須是異步的!也就是說:要一路 async 到頂層。
| 層級                            | 是否 async | 原因                    |
| ----------------------------- | -------- | --------------------- |
| DAO(使用 SQLiteAsyncConnection) | ? 必須異步   | SQLite 是 IO,使用異步 API  |
| 調用 DAO 的 Service              | ? 必須異步   | 調用異步方法 → 必須用 `await`  |
| 調用 Service 的 ViewModel        | ? 必須異步   | 繼續 `await` service 結果 || 情況               | 是否 async    |
| ---------------- | ----------- |
| 方法內部沒有任何異步調用     | ? 不需要 async |
| 方法只是封裝計算邏輯、純內存操作 | ? 不需要 async |你用的是 SQLiteAsyncConnection + HttpClient 這樣的異步庫,整個調用鏈(DAO → Service → ViewModel)都必須使用 async/await 才是正確做法。🎯 為什么 .Result 或 .Wait() 會“把線程卡住”?
原因是:
.Result 和 .Wait() 是同步阻塞方法,會強制當前線程“原地等到任務完成”,不能做別的事,也不會釋放線程。4.創建一個讀取postSQL數據庫的工具,生成實體類5432

PostgreSQLEntityGenerator.cs

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using Npgsql;namespace ConsoleApp1
{public class EntityGenerator{private readonly string _connectionString;private readonly string _outputPath;public EntityGenerator(string connectionString, string outputPath){_connectionString = connectionString;_outputPath = outputPath;}public void GenerateEntities(){try{// 確保輸出目錄存在if (!Directory.Exists(_outputPath)){Directory.CreateDirectory(_outputPath);}using (var connection = new NpgsqlConnection(_connectionString)){connection.Open();// 獲取所有表名var tables = GetTableNames(connection);foreach (var tableName in tables){Console.WriteLine($"正在生成實體類: {tableName}");GenerateEntityForTable(connection, tableName);}}Console.WriteLine($"實體類生成完成!輸出路徑: {_outputPath}");}catch (Exception ex){Console.WriteLine($"生成實體類時發生錯誤: {ex.Message}");throw;}}private List<string> GetTableNames(NpgsqlConnection connection){var tables = new List<string>();const string sql = @"SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_type = 'BASE TABLE'ORDER BY table_name";using (var command = new NpgsqlCommand(sql, connection))using (var reader = command.ExecuteReader()){while (reader.Read()){tables.Add(reader.GetString("table_name"));}}return tables;}private void GenerateEntityForTable(NpgsqlConnection connection, string tableName){var columns = GetTableColumns(connection, tableName);var entityCode = GenerateEntityCode(tableName, columns);var fileName = $"{ToPascalCase(tableName)}.cs";var filePath = Path.Combine(_outputPath, fileName);File.WriteAllText(filePath, entityCode, Encoding.UTF8);}private List<ColumnInfo> GetTableColumns(NpgsqlConnection connection, string tableName){var columns = new List<ColumnInfo>();const string sql = @"SELECT c.column_name,c.data_type,c.is_nullable,c.column_default,c.character_maximum_length,c.numeric_precision,c.numeric_scale,CASE WHEN pk.column_name IS NOT NULL THEN true ELSE false END as is_primary_keyFROM information_schema.columns cLEFT JOIN (SELECT ku.column_nameFROM information_schema.table_constraints tcJOIN information_schema.key_column_usage kuON tc.constraint_name = ku.constraint_nameAND tc.table_schema = ku.table_schemaWHERE tc.constraint_type = 'PRIMARY KEY'AND tc.table_name = @tableNameAND tc.table_schema = 'public') pk ON c.column_name = pk.column_nameWHERE c.table_name = @tableNameAND c.table_schema = 'public'ORDER BY c.ordinal_position";using (var command = new NpgsqlCommand(sql, connection)){command.Parameters.AddWithValue("@tableName", tableName);using (var reader = command.ExecuteReader()){while (reader.Read()){columns.Add(new ColumnInfo{Name = reader.GetString("column_name"),DataType = reader.GetString("data_type"),IsNullable = reader.GetString("is_nullable") == "YES",DefaultValue = reader.IsDBNull("column_default") ? null : reader.GetString("column_default"),MaxLength = reader.IsDBNull("character_maximum_length") ? (int?)null : reader.GetInt32("character_maximum_length"),Precision = reader.IsDBNull("numeric_precision") ? (int?)null : reader.GetInt32("numeric_precision"),Scale = reader.IsDBNull("numeric_scale") ? (int?)null : reader.GetInt32("numeric_scale"),IsPrimaryKey = reader.GetBoolean("is_primary_key")});}}}return columns;}private string GenerateEntityCode(string tableName, List<ColumnInfo> columns){var sb = new StringBuilder();var className = ToPascalCase(tableName);// 添加using語句sb.AppendLine("using System;");sb.AppendLine("using System.ComponentModel.DataAnnotations;");sb.AppendLine("using System.ComponentModel.DataAnnotations.Schema;");sb.AppendLine();// 添加命名空間sb.AppendLine("namespace Entities");sb.AppendLine("{");// 添加Table特性sb.AppendLine($"    [Table(\"{tableName}\")]");sb.AppendLine($"    public class {className}");sb.AppendLine("    {");// 生成屬性foreach (var column in columns){GenerateProperty(sb, column);}sb.AppendLine("    }");sb.AppendLine("}");return sb.ToString();}private void GenerateProperty(StringBuilder sb, ColumnInfo column){var propertyName = ToPascalCase(column.Name);var csharpType = GetCSharpType(column);// 添加注釋sb.AppendLine();sb.AppendLine($"        /// <summary>");sb.AppendLine($"        /// {column.Name}");sb.AppendLine($"        /// </summary>");// 添加特性if (column.IsPrimaryKey){sb.AppendLine("        [Key]");}sb.AppendLine($"        [Column(\"{column.Name}\")]");if (!column.IsNullable && csharpType != "string"){sb.AppendLine("        [Required]");}if (column.MaxLength.HasValue && csharpType == "string"){sb.AppendLine($"        [MaxLength({column.MaxLength.Value})]");}// 生成屬性sb.AppendLine($"        public {csharpType} {propertyName} {{ get; set; }}");}private string GetCSharpType(ColumnInfo column){var baseType = column.DataType.ToLower() switch{"integer" or "int4" => "int","bigint" or "int8" => "long","smallint" or "int2" => "short","boolean" or "bool" => "bool","real" or "float4" => "float","double precision" or "float8" => "double","numeric" or "decimal" => "decimal","text" or "varchar" or "character varying" or "char" or "character" => "string","timestamp" or "timestamp without time zone" => "DateTime","timestamp with time zone" or "timestamptz" => "DateTimeOffset","date" => "DateTime","time" or "time without time zone" => "TimeSpan","uuid" => "Guid","json" or "jsonb" => "string","bytea" => "byte[]",_ => "object"};// 如果字段可為空且不是引用類型,添加?if (column.IsNullable && baseType != "string" && baseType != "byte[]" && baseType != "object"){return baseType + "?";}return baseType;}private string ToPascalCase(string input){if (string.IsNullOrEmpty(input))return input;var parts = input.Split('_', '-');var sb = new StringBuilder();foreach (var part in parts){if (!string.IsNullOrEmpty(part)){sb.Append(char.ToUpper(part[0]));if (part.Length > 1)sb.Append(part[1..].ToLower());}}return sb.ToString();}}public class ColumnInfo{public string Name { get; set; }public string DataType { get; set; }public bool IsNullable { get; set; }public string DefaultValue { get; set; }public int? MaxLength { get; set; }public int? Precision { get; set; }public int? Scale { get; set; }public bool IsPrimaryKey { get; set; }}
}

Program.cs

using ConsoleApp1;try
{// 配置數據庫連接字符串var connectionString = "Host=localhost;Database=postgres;Username=postgres;Password=123456;";// 配置輸出路徑var outputPath = @"C:\MySoft\PostgreSQL\Models";// 創建生成器實例var generator = new EntityGenerator(connectionString, outputPath);// 生成實體類generator.GenerateEntities();Console.WriteLine("按任意鍵退出...");Console.ReadKey();
}
catch (Exception ex)
{Console.WriteLine($"程序執行出錯: {ex.Message}");Console.WriteLine("按任意鍵退出...");Console.ReadKey();
}
Console.WriteLine("Hello, World!");

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89997.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89997.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89997.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

B樹、B-樹與B+樹

B樹、B-tree與B樹 在計算機科學&#xff0c;尤其是數據庫和文件系統的領域中&#xff0c;B樹、B-tree和B樹是理解數據如何被高效存儲和檢索的關鍵。它們之間關系緊密&#xff0c;但功能和應用上又存在著決定性的差異。 一、 核心概念澄清&#xff1a;B樹就是B-tree 首先需要明確…

視頻格式轉換工廠v3.2.5,集音視頻、圖片處理78MB

今天&#xff0c;我們要介紹的是一款功能強大的視頻處理軟件——視頻格式轉換工廠。這款軟件已經完美破解&#xff0c;無需登錄即可享受全部高級功能。它不僅支持視頻格式轉換&#xff0c;還涵蓋了音頻、圖片處理等多種功能&#xff0c;是一款真正的多媒體處理工具。 視頻格式轉…

VUE 中父級組件使用JSON.stringify 序列化子組件傳遞循環引用錯誤

背景 VUE 中父級組件使用JSON.stringify 序列化子組件傳遞的數據會報錯 runtime-core.esm-bundler.js:268 Uncaught TypeError: Converting circular structure to JSON –> starting at object with constructor ‘Object’ — property ‘config’ closes the circle 原因…

HTTP,HTTPS

在網絡工程師、開發工程師、運維工程師等崗位的面試中&#xff0c;??HTTP/HTTPS?? 是高頻必考知識點&#xff0c;尤其在前端、后端、測試、DevOps等與網絡通信相關的職位中。以下是系統化的核心考點梳理&#xff0c;涵蓋基礎概念、協議機制、安全特性及應聘高頻問題。??一…

Nginx訪問日志分析在云服務器環境的技術實現與案例

在云計算時代&#xff0c;Nginx訪問日志分析已成為服務器運維的關鍵環節。本文將深入解析如何通過日志切割、實時監控和可視化展示三大技術路徑&#xff0c;實現云環境下Nginx日志的高效分析。我們將結合具體案例&#xff0c;演示從原始日志到運維決策的完整技術閉環&#xff0…

鴻蒙實現一次上傳多張圖片

記錄初接觸鴻蒙&#xff0c;遇到的一個問題&#xff0c;需求是點擊一個圖片上傳的號圖&#xff0c;訪問本地圖片&#xff0c;可以選擇多張圖片并上傳。下面是圖片上傳后的方法&#xff1a;//選擇圖片并上傳private async showPhotoPicker() {const maxImageCount 3;const rema…

【STM32】CRC 校驗函數

先上一下 CRC校驗 的源代碼&#xff1a; void crc_check(unsigned char *ptr,unsigned int len) //crc為開源函數 {unsigned long wcrc0XFFFF;//預置16位crc寄存器&#xff0c;初值全部為1unsigned char temp;//定義中間變量int i0,j0;//定義計數for(i0;i<len;i)//循環計算每…

【Java】SVN 版本控制軟件的快速安裝(可視化)

目錄 一、SVN 的概述 1.1 SVN 的概念 1.2 SVN 與 Git 的對比 1.3 SVN 軟件 二、SVN 的安裝 2.1 SVN 的工作流程 2.2 服務器端 SVN 的安裝 三、SVN 服務器端的配置 3.1 搭建項目 3.2 權限控制 四、SVN 客戶端的配置 4.1 SVN 客戶端的下載 4.2 客戶端連接 SVN 服務器…

Hadoop安全機制深度剖析:Kerberos認證與HDFS ACL細粒度權限控制

Hadoop安全機制概述在大數據時代&#xff0c;Hadoop作為分布式計算框架的核心組件&#xff0c;其安全性直接關系到企業數據資產的保護。隨著數據價值的不斷提升&#xff0c;Hadoop安全機制已從早期的"簡單信任模式"演進為包含多重防護措施的綜合體系&#xff0c;其重…

uniapp基本使用

資料 咸蝦米視頻 黑馬視頻 uniapp官方文檔 hbuilder 1.uniapp頁面生命周期 1.1 onLoad 還拿不到dom適合接受上頁的參數&#xff0c;聯網取數據&#xff0c;更新data。相當于created和beforeCreated期間主要的作用是比如說獲取url上的query參數 *url: ***/**?name張三&…

ssh2-sftp-client 簡化 sftp 文件傳輸的 node庫

ssh2-sftp-client 極大地簡化了通過 sftp 進行文件傳輸的復雜性。無論你是需要上傳、下載、刪除文件&#xff0c;還是列出目錄內容&#xff0c;可當簡易的部署腳步npm run deploy const SftpClient require(ssh2-sftp-client) const sftp new SftpClient()const config {hos…

數字美元與全球支付革命:穩定幣的興起與全球金融格局的重塑

一、數字美元的崛起&#xff1a;美國戰略布局與全球競爭1. 數字美元的定位與戰略意義 數字美元作為美國構建“數字美元帝國”的核心工具&#xff0c;旨在通過區塊鏈技術實現美元的數字化發行與流通&#xff0c;鞏固其全球儲備貨幣地位。其核心邏輯在于&#xff1a;技術賦能貨幣…

LeetCode 633.平方數之和

給定一個非負整數 c &#xff0c;你要判斷是否存在兩個整數 a 和 b&#xff0c;使得 a2 b2 c 。 示例 1&#xff1a; 輸入&#xff1a;c 5 輸出&#xff1a;true 解釋&#xff1a;1 * 1 2 * 2 5 示例 2&#xff1a; 輸入&#xff1a;c 3 輸出&#xff1a;false 提示&…

Spring Boot 使用Jasypt加密

一、配置Jasypt 1.在pom.xml中導入依賴 <!-- Jasypt 加密工具 --><dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>3.0.5</version></dependency&…

【電影剖析】千鈞一發

目錄 1 人物介紹 2 電影名解讀 3 電影開頭 3.1 電影開頭的兩段話 3.2 片頭設計 4 電影正文 4.1 “杰羅米”各種詭異的行為 4.2 文森特 – 失敗的man 4.3 真正的杰羅米以及假基因身份證 4.4 文森特新征程 4.5 基因人的不容易 4.6 睫毛被查出有問題 4.7 文森特身份初…

論文略讀:Arcee’s MergeKit: A Toolkit for Merging Large Language Models

emnlp 2024在過去的一年里&#xff0c;開源大型語言模型&#xff08;LLMs&#xff09;迅速發展&#xff0c;并已可通過 Hugging Face 模型庫獲取。這些模型的訓練規模可達數萬億個 token&#xff0c;參數量通常在 1 億至 700 億以上不等開源模型檢查點涵蓋了多種任務&#xff0…

刀客doc:Netflix與YouTube開始在廣告戰場正面交鋒

01廣告一開始并不是Netflix的核心業務&#xff0c;但眼下&#xff0c;廣告正逐步成為這家公司與YouTube正面對抗的關鍵戰場。在上周剛發布的Q2財報里&#xff0c;Netflix廣告層已覆蓋全球12個核心市場&#xff0c;月活躍用戶已經逼近9400萬&#xff0c;主要集中在CTV滲透率高的…

(四)Unity3d-ROS聯合仿真:turtlebot在Unity3d中仿真

運行環境Ubuntu20.04Unity3d 1.下載運行 &#xff08;1&#xff09;項目下載地址&#xff1a; Robotics-Nav2-SLAM-Example 最好執行下面命令能將子模塊也下載 git clone --recurse-submodule gitgithub.com:Unity-Technologies/Robotics-Nav2-SLAM-Example.gitgit submodu…

信息學奧賽一本通 1553:【例 2】暗的連鎖

【題目鏈接】 ybt 1553&#xff1a;【例 2】暗的連鎖 【題目考點】 1. 樹上差分&#xff1a;邊差分 類似對差分序列進行修改可以完成對原序列的區間修改。對樹上邊差分進行修改可以完成對樹上一條路徑中所有邊的邊權進行修改。 一條邊的差分值為該邊的權值減去該邊連接的深…

二分查找-852.山峰數組的峰頂索引-力扣(LeetCode)

一、題目解析1.山峰數組數據嚴格滿足arr[0]<arr[1]……<arr[i]>arr[i1]……arr[arr.size()-1]2.時間復雜度要求為O(logN)二、算法解析解法1&#xff1a;暴力解法-O(N)遍歷數組arr&#xff0c;結合山峰數組性質&#xff0c;我們發現峰頂存在arr[i]>arr[i-1]&#xf…