diff --git a/Src/Asp.NetCore2/DuckDBTest/1_CodeFirst.cs b/Src/Asp.NetCore2/DuckDBTest/1_CodeFirst.cs
new file mode 100644
index 000000000..14f37a858
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/1_CodeFirst.cs
@@ -0,0 +1,134 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OrmTest
+{
+ ///
+ /// Class for demonstrating CodeFirst initialization operations
+ /// 用于展示 CodeFirst 初始化操作的类
+ ///
+ public class _1_CodeFirst
+ {
+
+ public static void Init()
+ {
+ // Get a new database instance
+ // 获取新的数据库实例
+ var db = DbHelper.GetNewDb();
+
+ // Create the database if it doesn't exist
+ // 如果数据库不存在,则创建数据库
+ db.DbMaintenance.CreateDatabase();
+
+ // Initialize tables based on UserInfo001 entity class
+ // 根据 UserInfo001 实体类初始化表
+ db.CodeFirst.InitTables();
+
+ //Table structure and class are different
+ //表结构和类存在差异 初始化表
+ db.CodeFirst.InitTables();
+
+ //Insert
+ //插入
+ var id=db.Insertable(new UserInfo001()
+ {
+ Context = "Context",
+ Email="dfafa@qq.com",
+ Price=Convert.ToDecimal(1.1),
+ UserName="admin",
+ RegistrationDate=DateTime.Now,
+
+ }).ExecuteReturnIdentity();
+
+ //Query
+ //查询
+ var userInfo=db.Queryable().InSingle(id);
+
+ //Update
+ //更新
+ db.Updateable(userInfo).ExecuteCommand();
+
+ //Delete
+ //删除
+ db.Deleteable(userInfo).ExecuteCommand();
+ }
+
+ ///
+ /// User information entity class
+ /// 用户信息实体类
+ ///
+ public class UserInfo001
+ {
+ ///
+ /// User ID (Primary Key)
+ /// 用户ID(主键)
+ ///
+ [SugarColumn(IsIdentity = true, IsPrimaryKey = true)]
+ public int UserId { get; set; }
+
+ ///
+ /// User name
+ /// 用户名
+ ///
+ [SugarColumn(Length = 50, IsNullable = false)]
+ public string UserName { get; set; }
+
+ ///
+ /// User email
+ /// 用户邮箱
+ ///
+ [SugarColumn(IsNullable = true)]
+ public string Email { get; set; }
+
+
+ ///
+ /// Product price
+ /// 产品价格
+ ///
+ public decimal Price { get; set; }
+
+ ///
+ /// User context
+ /// 用户内容
+ ///
+ [SugarColumn(ColumnDataType = StaticConfig.CodeFirst_BigString, IsNullable = true)]
+ public string Context { get; set; }
+
+ ///
+ /// User registration date
+ /// 用户注册日期
+ ///
+ [SugarColumn(IsNullable = true)]
+ public DateTime? RegistrationDate { get; set; }
+ }
+
+
+ ///
+ /// User information entity class
+ /// 用户信息实体类
+ ///
+ [SugarTable("UserInfoAAA01")]
+ public class UserInfo002
+ {
+ ///
+ /// User ID (Primary Key)
+ /// 用户ID(主键)
+ ///
+ [SugarColumn(IsIdentity = true,ColumnName ="Id", IsPrimaryKey = true)]
+ public int UserId { get; set; }
+
+ ///
+ /// User name
+ /// 用户名
+ ///
+ [SugarColumn(Length = 50,ColumnName ="Name", IsNullable = false)]
+ public string UserName { get; set; }
+
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/2_DbFirst.cs b/Src/Asp.NetCore2/DuckDBTest/2_DbFirst.cs
new file mode 100644
index 000000000..a4ba49fc0
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/2_DbFirst.cs
@@ -0,0 +1,136 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OrmTest
+{
+ internal class _2_DbFirst
+ {
+ ///
+ /// 初始化方法,包含各种DbFirst操作的演示
+ /// Initialization method containing demonstrations of various DbFirst operations
+ ///
+ public static void Init()
+ {
+ var db = DbHelper.GetNewDb();
+
+ // 生成干净的实体类文件
+ // Generate clean entity class files
+ Demo1(db);
+
+ // 生成带有SqlSugar特性的实体类文件
+ // Generate entity class files with SqlSugar attributes
+ Demo2(db);
+
+ // 支持字符串类型的Nullable特性
+ // Support String Nullable attribute
+ Demo3(db);
+
+ // 格式化类名、属性名和文件名
+ // Format class names, property names, and file names
+ Demo4(db);
+
+ // 条件过滤生成实体类文件
+ // Generate entity class files with condition filtering
+ Demo5(db);
+
+ // 修改模版生成实体类文件(禁用IsCreateAttribute,避免冲突)
+ // Generate entity class files with modified templates (disable IsCreateAttribute to avoid conflicts)
+ Demo6(db);
+ }
+
+ ///
+ /// 生成干净的实体类文件
+ /// Generate clean entity class files
+ ///
+ private static void Demo1(SqlSugarClient db)
+ {
+ db.DbFirst.CreateClassFile("c:\\Demo\\1", "Models");
+ }
+
+ ///
+ /// 生成带有SqlSugar特性的实体类文件
+ /// Generate entity class files with SqlSugar attributes
+ ///
+ private static void Demo2(SqlSugarClient db)
+ {
+ db.DbFirst.IsCreateAttribute().CreateClassFile("c:\\Demo\\2", "Models");
+ }
+
+ ///
+ /// 支持字符串类型的Nullable特性
+ /// Support String Nullable attribute
+ ///
+ private static void Demo3(SqlSugarClient db)
+ {
+ db.DbFirst.IsCreateAttribute().StringNullable().CreateClassFile("c:\\Demo\\3", "Models");
+ }
+
+ ///
+ /// 格式化类名、属性名和文件名
+ /// Format class names, property names, and file names
+ ///
+ private static void Demo4(SqlSugarClient db)
+ {
+ db.DbFirst
+ .IsCreateAttribute()
+ .FormatFileName(it => "File_" + it)
+ .FormatClassName(it => "Class_" + it)
+ .FormatPropertyName(it => "Property_" + it)
+ .CreateClassFile("c:\\Demo\\4", "Models");
+ }
+
+ ///
+ /// 条件过滤生成实体类文件
+ /// Generate entity class files with condition filtering
+ ///
+ private static void Demo5(SqlSugarClient db)
+ {
+ db.DbFirst.IsCreateAttribute().Where(it => it.ToLower() == "userinfo001").CreateClassFile("c:\\Demo\\5", "Models");
+ }
+
+ ///
+ /// 修改模版生成实体类文件(禁用IsCreateAttribute,避免冲突)
+ /// Generate entity class files with modified templates (disable IsCreateAttribute to avoid conflicts)
+ ///
+ private static void Demo6(SqlSugarClient db)
+ {
+ db.DbFirst
+ // 类
+ .SettingClassTemplate(old => { return old;/* 修改old值替换 */ })
+ // 类构造函数
+ .SettingConstructorTemplate(old => { return old;/* 修改old值替换 */ })
+ .SettingNamespaceTemplate(old =>
+ {
+ return old + "\r\nusing SqlSugar;"; // 追加引用SqlSugar
+ })
+ // 属性备注
+ .SettingPropertyDescriptionTemplate(old => { return old;/* 修改old值替换 */})
+
+ // 属性:新重载 完全自定义用配置
+ .SettingPropertyTemplate((columns, temp, type) =>
+ {
+
+ var columnattribute = "\r\n [SugarColumn({0})]";
+ List attributes = new List();
+ if (columns.IsPrimarykey)
+ attributes.Add("IsPrimaryKey=true");
+ if (columns.IsIdentity)
+ attributes.Add("IsIdentity=true");
+ if (attributes.Count == 0)
+ {
+ columnattribute = "";
+ }
+ return temp.Replace("{PropertyType}", type)
+ .Replace("{PropertyName}", columns.DbColumnName)
+ .Replace("{SugarColumn}", string.Format(columnattribute, string.Join(",", attributes)));
+ })
+
+ .CreateClassFile("c:\\Demo\\6");
+ }
+ }
+}
+
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/3_EasyQuery.cs b/Src/Asp.NetCore2/DuckDBTest/3_EasyQuery.cs
new file mode 100644
index 000000000..b4544bab0
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/3_EasyQuery.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using SqlSugar;
+
+namespace OrmTest
+{
+ internal class _3_EasyQuery
+ {
+ ///
+ /// 初始化方法,包含各种查询操作的演示
+ /// Initialization method containing demonstrations of various query operations
+ ///
+ public static void Init()
+ {
+ // 创建表并插入一条记录
+ // Create table and insert a record
+ CreateTable();
+
+ // 查询所有学生信息
+ // Query all student records
+ GetAllStudents();
+
+ // 查询学生总数
+ // Get the total count of students
+ GetStudentCount();
+
+ // 按条件查询学生信息
+ // Query student records based on conditions
+ GetStudentsByCondition();
+
+ // 模糊查询学生信息(名字包含"jack"的学生)
+ // Fuzzy search for student records (students with names containing "jack")
+ GetStudentsByName("jack");
+
+ // 根据学生ID查询单个学生
+ // Query a single student by student ID
+ GetStudentById(1);
+
+ // 获取Student03表中的最大Id
+ // Get the maximum ID from the Student03 table
+ GetMaxStudentId();
+
+ // 简单排序(按照Id降序排序)
+ // Simple sorting (sorting by Id in descending order)
+ GetStudentsOrderedByIdDesc();
+
+ // 查询学生姓名列表
+ // Query the list of student names
+ GetStudentNames();
+ }
+
+ ///
+ /// 创建表并插入一条记录
+ /// Create table and insert a record
+ ///
+ private static void CreateTable()
+ {
+ SqlSugarClient db = DbHelper.GetNewDb();
+ db.CodeFirst.InitTables();
+ db.Insertable(new Student03() { Name = "name" + SnowFlakeSingle.Instance.NextId() })
+ .ExecuteCommand();
+ }
+
+ ///
+ /// 查询所有学生信息
+ /// Query all student records
+ ///
+ private static void GetAllStudents()
+ {
+ SqlSugarClient db = DbHelper.GetNewDb();
+ var students = db.Queryable().ToList();
+ // 处理查询结果
+ // Process the query results
+ }
+
+ ///
+ /// 查询学生总数
+ /// Get the total count of students
+ ///
+ private static void GetStudentCount()
+ {
+ SqlSugarClient db = DbHelper.GetNewDb();
+ var count = db.Queryable().Count();
+ // 处理查询结果
+ // Process the query results
+ }
+
+ ///
+ /// 按条件查询学生信息
+ /// Query student records based on conditions
+ ///
+ private static void GetStudentsByCondition()
+ {
+ SqlSugarClient db = DbHelper.GetNewDb();
+
+ // 查询name字段不为null的学生
+ // Query students where the 'name' field is not null
+ var studentsWithNameNotNull = db.Queryable().Where(it => it.Name != null).ToList();
+
+ // 查询name字段为null的学生
+ // Query students where the 'name' field is null
+ var studentsWithNameNull = db.Queryable().Where(it => it.Name == null).ToList();
+
+ // 查询name字段不为空的学生
+ // Query students where the 'name' field is not empty
+ var studentsWithNameNotEmpty = db.Queryable().Where(it => it.Name != "").ToList();
+
+ // 多条件查询
+ // Query students with multiple conditions
+ var studentsWithMultipleConditions = db.Queryable().Where(it => it.Id > 10 && it.Name == "a").ToList();
+
+ // 动态OR查询
+ // Dynamic OR query
+ var exp = Expressionable.Create();
+ exp.OrIF(true, it => it.Id == 1);
+ exp.Or(it => it.Name.Contains("jack"));
+ var studentsWithDynamicOr = db.Queryable().Where(exp.ToExpression()).ToList();
+
+ }
+
+ ///
+ /// 模糊查询学生信息
+ /// Fuzzy search for student records
+ ///
+ private static void GetStudentsByName(string keyword)
+ {
+ SqlSugarClient db = DbHelper.GetNewDb();
+ var students = db.Queryable().Where(it => it.Name.Contains(keyword)).ToList();
+ // 处理查询结果
+ // Process the query results
+ }
+
+ ///
+ /// 根据学生ID查询单个学生
+ /// Query a single student by student ID
+ ///
+ private static void GetStudentById(int id)
+ {
+ SqlSugarClient db = DbHelper.GetNewDb();
+ var student = db.Queryable().Single(it => it.Id == id);
+ // 处理查询结果
+ // Process the query results
+ }
+
+ ///
+ /// 获取Student03表中的最大Id
+ /// Get the maximum ID from the Student03 table
+ ///
+ private static void GetMaxStudentId()
+ {
+ SqlSugarClient db = DbHelper.GetNewDb();
+ var maxId = db.Queryable().Max(it => it.Id);
+ // 处理查询结果
+ // Process the query results
+ }
+
+ ///
+ /// 简单排序(按照Id降序排序)
+ /// Simple sorting (sorting by Id in descending order)
+ ///
+ private static void GetStudentsOrderedByIdDesc()
+ {
+ SqlSugarClient db = DbHelper.GetNewDb();
+ var students = db.Queryable().OrderBy(sc => sc.Id, OrderByType.Desc).ToList();
+ // 处理查询结果
+ // Process the query results
+ }
+
+ ///
+ /// 查询学生姓名列表
+ /// Query the list of student names
+ ///
+ private static void GetStudentNames()
+ {
+ SqlSugarClient db = DbHelper.GetNewDb();
+ var studentNames = db.Queryable().Select(it => it.Name).ToList();
+ // 处理查询结果
+ // Process the query results
+ }
+
+ public class Student03
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/4_JoinQuery.cs b/Src/Asp.NetCore2/DuckDBTest/4_JoinQuery.cs
new file mode 100644
index 000000000..979152df8
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/4_JoinQuery.cs
@@ -0,0 +1,171 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static OrmTest._4_JoinQuery;
+
+namespace OrmTest
+{
+ internal class _4_JoinQuery
+ {
+ public static void Init()
+ {
+ InitializeDatabase();
+ SyntaxSugar1();
+ SyntaxSugar2();
+ SyntaxSugar3();
+ }
+ ///
+ /// 使用语法糖1进行联表查询。
+ /// Performs a Join query using Syntax Sugar 1.
+ ///
+ /// 查询结果列表。The list of query results.
+ public static List SyntaxSugar1()
+ {
+ var db = DbHelper.GetNewDb();
+ var query = db.Queryable()
+ .LeftJoin((o, cus) => o.CustomId == cus.Id)
+ .LeftJoin((o, cus, oritem) => o.Id == oritem.OrderId)
+ .Where(o => o.Id == 1)
+ .Select((o, cus, oritem) => new ViewOrder2 { Id = o.Id,Name=o.Name, CustomName = cus.Name })
+ .ToList();
+
+ return query;
+ }
+
+ ///
+ /// 使用语法糖2进行联表查询。
+ /// Performs a Join query using Syntax Sugar 2.
+ ///
+ /// 查询结果列表。The list of query results.
+ public static List SyntaxSugar2()
+ {
+ var db = DbHelper.GetNewDb();
+ var rightQueryable = db.Queryable()
+ .LeftJoin((o, i) => o.Id == i.Id)
+ .Select(o => o);
+
+ var list = db.Queryable()
+ .LeftJoin(rightQueryable, (c, j) => c.CustomId == j.Id)
+ .Select(c => c)
+ .ToList();
+ return list;
+ }
+
+ ///
+ /// 使用语法糖3进行联表查询。
+ /// Performs a Join query using Syntax Sugar 3.
+ ///
+ /// 查询结果列表。The list of query results.
+ public static List SyntaxSugar3()
+ {
+ var db = DbHelper.GetNewDb();
+ var list = db.Queryable((o, i, c) => o.Id == i.OrderId && c.Id == o.CustomId)
+ .Select((o, i, c) => new ViewOrder2 { Id = o.Id, Name = o.Name, CustomName = c.Name })
+ .ToList();
+
+ return list;
+ }
+
+
+ static void InitializeDatabase()
+ {
+ // Initialize order data
+ // 初始化订单数据
+ var orders = new List
+ {
+ new Order { Id = 1, Name = "Order 1", CustomId = 1 },
+ new Order { Id = 2, Name = "Order 2", CustomId = 2 },
+ new Order { Id = 3, Name = "Order 3", CustomId = 1 },
+ };
+
+ // Initialize order details data
+ // 初始化订单详情数据
+ var orderDetails = new List
+ {
+ new OrderDetail { Id = 1, OrderId = 1 },
+ new OrderDetail { Id = 2, OrderId = 2 },
+ new OrderDetail { Id = 3, OrderId = 3 },
+ };
+
+ // Initialize customer data
+ // 初始化客户数据
+ var customers = new List
+ {
+ new Custom { Id = 1, Name = "Customer 1" },
+ new Custom { Id = 2, Name = "Customer 2" },
+ new Custom { Id = 3, Name = "Customer 3" },
+ };
+
+ // Get database connection
+ // 获取数据库连接
+ var db = DbHelper.GetNewDb();
+
+ // Initialize database tables and truncate data
+ // 初始化数据库表并清空数据
+ db.CodeFirst.InitTables();
+ db.DbMaintenance.TruncateTable();
+
+ // Insert data into tables
+ // 向表中插入数据
+ db.Insertable(orders).ExecuteCommand();
+ db.Insertable(orderDetails).ExecuteCommand();
+ db.Insertable(customers).ExecuteCommand();
+ }
+
+ ///
+ /// 订单实体类。
+ /// Order entity class.
+ ///
+ [SqlSugar.SugarTable("Order04")]
+ public class Order
+ {
+ [SqlSugar.SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public int CustomId { get; set; }
+ // 其他订单相关属性...
+ }
+
+ ///
+ /// 订单详情实体类。
+ /// Order detail entity class.
+ ///
+ [SqlSugar.SugarTable("OrderDetail04")]
+ public class OrderDetail
+ {
+ [SqlSugar.SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+ public int OrderId { get; set; }
+ // 其他订单详情相关属性...
+ }
+
+ ///
+ /// 客户实体类。
+ /// Customer entity class.
+ ///
+ [SqlSugar.SugarTable("Custom04")]
+ public class Custom
+ {
+ [SqlSugar.SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+ public string Name { get; set; }
+ // 其他客户相关属性...
+ }
+
+
+
+ ///
+ /// 类1实体类。
+ /// Class1 entity class.
+ ///
+ public class ViewOrder2
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string CustomName { get; set; }
+ // 其他类1相关属性...
+ }
+ }
+}
diff --git a/Src/Asp.NetCore2/DuckDBTest/4_Subquery.cs b/Src/Asp.NetCore2/DuckDBTest/4_Subquery.cs
new file mode 100644
index 000000000..56c6e9956
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/4_Subquery.cs
@@ -0,0 +1,68 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OrmTest
+{
+ public class _4_Subquery
+ {
+ public static void Init()
+ {
+
+ var db = DbHelper.GetNewDb();
+
+ db.CodeFirst.InitTables();
+ db.DbMaintenance.TruncateTable();
+
+ db.Insertable(new Student() { Id = 1, SchoolId = 1 }).ExecuteCommand();
+ db.Insertable(new School() { Id = 1, Name = "Harvard School" }).ExecuteCommand();
+ db.Insertable(new Student() { Id = 2, SchoolId = 2 }).ExecuteCommand();
+ db.Insertable(new School() { Id = 2, Name = "haha School" }).ExecuteCommand();
+
+ //subquery select
+ var result = db.Queryable()
+ .Select(st => new
+ {
+ SchoolName = SqlFunc.Subqueryable().Where(s => s.Id == st.SchoolId).Select(s => s.Name),
+ MaxSchoolId = SqlFunc.Subqueryable().Where(s => s.Id == st.SchoolId).Select(s => SqlFunc.AggregateMax(s.Id)),
+ MaxSchoolId2 = SqlFunc.Subqueryable().Where(s => s.Id == st.SchoolId).Max(s => s.Id),
+ })
+ .ToList();
+
+ //Exists:
+ //SELECT [Id],[SchoolId] FROM [Student0402] [it] WHERE (EXISTS ( SELECT * FROM [School0402] [s] WHERE ( [Id] = [it].[SchoolId] ) ))
+ var result2 = db.Queryable()
+ .Where(it => SqlFunc.Subqueryable().Where(s => s.Id == it.SchoolId).Any())
+ .ToList();
+
+ //In:
+ //SELECT [Id],[SchoolId] FROM [Student0402] [it] WHERE [Id] in (SELECT [Id] FROM [School0402] [s] GROUP BY [Id])
+ var result3 = db.Queryable()
+ .Where(it => it.Id == SqlFunc.Subqueryable().GroupBy(s => s.Id).Select(s => s.Id))
+ .ToList();
+
+ //Equal:
+ //SELECT [Id],[SchoolId] FROM [Student0402] [it] WHERE ( [Id] =(SELECT TOP 1 [s].[Id] FROM [School0402] [s] ))
+ var result4 = db.Queryable()
+ .Where(it => it.Id == SqlFunc.Subqueryable().Select(s => s.Id))
+ .ToList();
+ }
+
+ [SugarTable("Student0402")]
+ public class Student
+ {
+ public int Id { get; set; }
+ public int SchoolId { get; set; }
+ }
+ [SugarTable("School0402")]
+ public class School
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+
+ }
+}
diff --git a/Src/Asp.NetCore2/DuckDBTest/5_PageQuery.cs b/Src/Asp.NetCore2/DuckDBTest/5_PageQuery.cs
new file mode 100644
index 000000000..fba71c6f7
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/5_PageQuery.cs
@@ -0,0 +1,112 @@
+using OrmTest;
+using SqlSugar;
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+
+public class _5_PageQuery
+{
+ public static void Init()
+ {
+
+ int pagenumber = 1;
+ int pageSize = 20;
+ int totalCount = 0;
+
+ SqlSugarClient db = DbHelper.GetNewDb();
+
+ //建表
+ //Create table
+ AddTestData(db);
+
+ // 同步分页方法
+ // Synchronous pagination method
+ SyncPagination(db, pagenumber, pageSize, ref totalCount);
+
+ // 异步分页方法
+ // Asynchronous pagination method
+ AsyncPagination(db, pagenumber, pageSize) .GetAwaiter() .GetResult();
+ }
+
+ public static void AddTestData(SqlSugarClient db)
+ {
+
+ //建表
+ //Create table
+ db.CodeFirst.InitTables();
+
+ // 添加学校数据
+ // Add school data
+ var school1 = new School { Name = "School A" };
+ var school2 = new School { Name = "School B" };
+ db.Insertable(school1).ExecuteCommand();
+ db.Insertable(school2).ExecuteCommand();
+
+ // 添加学生数据
+ // Add student data
+ var student1 = new Student { SchoolId = school1.Id, Name = "John", CreateTime = DateTime.Now };
+ var student2 = new Student { SchoolId = school1.Id, Name = "Alice", CreateTime = DateTime.Now };
+
+ db.Insertable(student1).ExecuteCommand();
+ db.Insertable(student2).ExecuteCommand();
+
+ Console.WriteLine("Test data added successfully.");
+ }
+
+ ///
+ /// 同步分页示例
+ /// Synchronous pagination example
+ ///
+ /// 数据库连接对象 Database connection object
+ /// 页码 Page number
+ /// 每页大小 Page size
+ /// 总记录数 Total record count
+ public static void SyncPagination(SqlSugarClient db, int pagenumber, int pageSize, ref int totalCount)
+ {
+ // 同步单表分页
+ // Synchronous pagination for a single table
+ var page = db.Queryable().ToPageList(pagenumber, pageSize, ref totalCount);
+
+ // 同步多表分页
+ // Synchronous pagination for multiple tables
+ var list = db.Queryable().LeftJoin((st, sc) => st.SchoolId == sc.Id)
+ .Select((st, sc) => new { Id = st.Id, Name = st.Name, SchoolName = sc.Name })
+ .ToPageList(pagenumber, pageSize, ref totalCount);
+
+ // offset分页
+ // offset pagination
+ var sqlServerPage = db.Queryable().ToOffsetPage(pagenumber, pageSize);
+
+ }
+
+ ///
+ /// 异步分页示例
+ /// Asynchronous pagination example
+ ///
+ /// 数据库连接对象 Database connection object
+ /// 页码 Page number
+ /// 每页大小 Page size
+ public static async Task AsyncPagination(SqlSugarClient db, int pagenumber, int pageSize)
+ {
+ RefAsync total = 0;
+ // 异步分页
+ // Asynchronous pagination
+ var orders = await db.Queryable().ToPageListAsync(pagenumber, pageSize, total);
+ }
+ [SugarTable("Student05")]
+ public class Student
+ {
+ [SugarColumn(IsIdentity =true,IsPrimaryKey =true)]
+ public int Id { get; set; }
+ public int SchoolId { get; set; }
+ public string Name { get; set; }
+ public DateTime CreateTime { get; set; }
+ }
+ [SugarTable("School05")]
+ public class School
+ {
+ [SugarColumn(IsIdentity = true, IsPrimaryKey = true)]
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/6_NavigationPropertyQuery.cs b/Src/Asp.NetCore2/DuckDBTest/6_NavigationPropertyQuery.cs
new file mode 100644
index 000000000..6dec5075e
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/6_NavigationPropertyQuery.cs
@@ -0,0 +1,268 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OrmTest
+{
+ internal class _6_NavQuery
+ {
+ ///
+ /// Initialize navigation query examples.
+ /// 初始化导航查询示例。
+ ///
+ public static void Init()
+ {
+ var db = DbHelper.GetNewDb();
+
+ // Initialize database table structures.
+ // 初始化数据库表结构。
+ InitializeDatabase(db);
+
+ // One-to-One navigation query test.
+ // 一对一导航查询测试。
+ OneToOneTest(db);
+
+ // One-to-Many navigation query test.
+ // 一对多导航查询测试。
+ OneToManyTest(db);
+
+ // Many-to-Many navigation query test.
+ // 多对多导航查询测试。
+ ManyToManyTest(db);
+ }
+
+ ///
+ /// Test many-to-many navigation queries.
+ /// 测试多对多导航查询。
+ ///
+ private static void ManyToManyTest(SqlSugarClient db)
+ {
+ // Many-to-many navigation query, query table A and include its BList.
+ // 多对多导航查询,查询A表,并包含其BList。
+ var list4 = db.Queryable().Includes(it => it.BList).ToList();
+
+ // Many-to-many navigation query with filtered BList while preserving the original A records, regardless of the filter on BList.
+ // 使用过滤条件的多对多导航查询,在过滤BList的同时保持A表的原始记录,不受BList过滤条件的影响。
+ var list5 = db.Queryable().Includes(it => it.BList.Where(s => s.BId == 1).ToList()).ToList();
+
+ // Many-to-many navigation query with filtered A records while preserving the original BList, regardless of the filter on A records.
+ // 使用过滤条件的多对多导航查询,在过滤A表的同时保持BList的原始记录,不受A表过滤条件的影响。
+ var list6 = db.Queryable().Includes(it => it.BList)
+ .Where(it =>it.BList.Any(s => s.BId == 1)).ToList();
+
+ // Many-to-many navigation query with filtered BList and filtered A records, but not preserving the original A and B records.
+ // 使用过滤条件的多对多导航查询,在A表中过滤BList并过滤A记录,但不保持A表和B表的原始记录。
+ var list7 = db.Queryable()
+ .Includes(it => it.BList.Where(s => s.BId == 1).ToList())
+ .Where(it => it.BList.Any(s => s.BId == 1)).ToList();
+ }
+
+ ///
+ /// Test one-to-many navigation queries.
+ /// 测试一对多导航查询。
+ ///
+ private static void OneToManyTest(SqlSugarClient db)
+ {
+ // One-to-many navigation query, query table Student and include its Books.
+ // 一对多导航查询,查询Student表,并包含其Books。
+ var list4 = db.Queryable().Includes(it => it.Books).ToList();
+
+ // One-to-many navigation query with filtered Books while preserving the original Student records, regardless of the filter on Books.
+ // 使用过滤条件的一对多导航查询,在过滤Books的同时保持Student表的原始记录,不受Books过滤条件的影响。
+ var list5 = db.Queryable().Includes(it => it.Books.Where(s => s.BookId == 1).ToList()).ToList();
+
+ // One-to-many navigation query with filtered Student records while preserving the original Books, regardless of the filter on Student records.
+ // 使用过滤条件的一对多导航查询,在过滤Student表的同时保持Books的原始记录,不受Student表过滤条件的影响。
+ var list6 = db.Queryable().Includes(it => it.Books)
+ .Where(it => it.Books.Any(s => s.BookId == 1)).ToList();
+
+ // One-to-many navigation query with filtered Books and filtered Student records, but not preserving the original Student and Books records.
+ // 使用过滤条件的一对多导航查询,在Student表中过滤Books并过滤Student记录,但不保持Student表和Books表的原始记录。
+ var list7 = db.Queryable()
+ .Includes(it => it.Books.Where(s => s.BookId == 1).ToList())
+ .Where(it => it.Books.Any(s => s.BookId == 1)).ToList();
+ }
+
+ ///
+ /// Test one-to-one navigation queries.
+ /// 测试一对一导航查询。
+ ///
+ private static void OneToOneTest(SqlSugarClient db)
+ {
+ // One-to-one navigation query with condition, query table Student and include its associated School with specific SchoolId.
+ // 带条件的一对一导航查询,查询Student表,并包含其关联的School表,条件为特定的SchoolId。
+ var list = db.Queryable()
+ .Where(it => it.School.SchoolId == 1)
+ .ToList();
+
+ // Inner join navigation query, query table Student and include its associated School.
+ // 内连接导航查询,查询Student表,并包含其关联的School表。
+ var list2 = db.Queryable().IncludeInnerJoin(it => it.School)
+ .ToList();
+
+ // Includes navigation query, query table Student and include its associated School.
+ // 包含导航查询,查询Student表,并包含其关联的School表。
+ var list3 = db.Queryable().Includes(it => it.School).ToList();
+ }
+
+ ///
+ /// Initialize database tables and insert sample data for navigation query examples.
+ /// 初始化导航查询示例的数据库表并插入示例数据。
+ ///
+ private static void InitializeDatabase(SqlSugarClient db)
+ {
+ // Initialize and truncate tables for Student, School, and Book entities.
+ // 初始化并清空Student、School和Book表。
+ db.CodeFirst.InitTables();
+ db.DbMaintenance.TruncateTable();
+
+ // Sample data for Student, School, and Book entities.
+ // Student、School和Book表的示例数据。
+ var students = new List
+ {
+ new Student
+ {
+ Name = "Student 1",
+ SexCode = "M",
+ School = new School { SchoolName = "School 1" },
+ Books = new List
+ {
+ new Book { Name = "Book 1" },
+ new Book { Name = "Book 2" }
+ }
+ },
+ new Student
+ {
+ Name = "Student 2",
+ SexCode = "F",
+ School = new School { SchoolName = "School 2" },
+ Books = new List
+ {
+ new Book { Name = "Book 3" }
+ }
+ }
+ };
+
+ // Insert sample data for Student, School, and Book entities using navigation properties.
+ // 使用导航属性插入Student、School和Book表的示例数据。
+ db.InsertNav(students)
+ .Include(it => it.School)
+ .Include(it => it.Books).ExecuteCommand();
+
+ // Initialize and truncate tables for A, B, and ABMapping entities.
+ // 初始化并清空A、B和ABMapping表。
+ db.CodeFirst.InitTables();
+ db.DbMaintenance.TruncateTable();
+
+ // Sample data for A, B, and ABMapping entities.
+ // A、B和ABMapping表的示例数据。
+ List a1 = new List { new A() { Name = "A1" }, new A() { Name = "A2" } };
+ B b1 = new B { Name = "B1" };
+ B b2 = new B { Name = "B2" };
+ a1[0].BList = new List { b1, b2 };
+
+ // Insert sample data for A, B, and ABMapping entities using navigation properties.
+ // 使用导航属性插入A、B和ABMapping表的示例数据。
+ db.InsertNav(a1).Include(x => x.BList).ExecuteCommand();
+ }
+
+ ///
+ /// Student entity representing the Student table in the database.
+ /// 表示数据库中Student表的Student实体类。
+ ///
+ [SugarTable("Student06")]
+ public class Student
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int StudentId { get; set; }
+ public string Name { get; set; }
+ public string SexCode { get; set; }
+ public int SchoolId { get; set; }
+
+ // One-to-One navigation property to School entity.
+ // 与School实体的一对一导航属性。
+ [Navigate(NavigateType.OneToOne, nameof(SchoolId))]
+ public School School { get; set; }
+
+ // One-to-Many navigation property to Book entities.
+ // 与Book实体的一对多导航属性。
+ [Navigate(NavigateType.OneToMany, nameof(Book.StudentId))]
+ public List Books { get; set; }
+ }
+
+ ///
+ /// School entity representing the School table in the database.
+ /// 表示数据库中School表的School实体类。
+ ///
+ [SugarTable("School06")]
+ public class School
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int SchoolId { get; set; }
+ public string SchoolName { get; set; }
+ }
+
+ ///
+ /// Book entity representing the Book table in the database.
+ /// 表示数据库中Book表的Book实体类。
+ ///
+ [SugarTable("Book06")]
+ public class Book
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int BookId { get; set; }
+ public string Name { get; set; }
+ public int StudentId { get; set; }
+ }
+
+ ///
+ /// A entity representing the A table in the database for many-to-many relationship.
+ /// 表示多对多关系中数据库中A表的A实体类。
+ ///
+ [SugarTable("A06")]
+ public class A
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int AId { get; set; }
+ public string Name { get; set; }
+
+ // Many-to-Many navigation property to B entities using ABMapping table.
+ // 与B实体的多对多导航属性,使用ABMapping表。
+ [Navigate(typeof(ABMapping), nameof(ABMapping.AId), nameof(ABMapping.BId))]
+ public List BList { get; set; }
+ }
+
+ ///
+ /// B entity representing the B table in the database for many-to-many relationship.
+ /// 表示多对多关系中数据库中B表的B实体类。
+ ///
+ [SugarTable("B06")]
+ public class B
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int BId { get; set; }
+ public string Name { get; set; }
+
+ // Many-to-Many navigation property to A entities using ABMapping table.
+ // 与A实体的多对多导航属性,使用ABMapping表。
+ [Navigate(typeof(ABMapping), nameof(ABMapping.BId), nameof(ABMapping.AId))]
+ public List AList { get; set; }
+ }
+
+ ///
+ /// ABMapping entity representing the intermediate table for many-to-many relationship between A and B entities.
+ /// 表示A和B实体之间多对多关系的中间表的ABMapping实体类。
+ ///
+ [SugarTable("ABMapping06")]
+ public class ABMapping
+ {
+ [SugarColumn(IsPrimaryKey = true)]
+ public int AId { get; set; }
+ [SugarColumn(IsPrimaryKey = true)]
+ public int BId { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/7_GroupQuery.cs b/Src/Asp.NetCore2/DuckDBTest/7_GroupQuery.cs
new file mode 100644
index 000000000..6eabe8d54
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/7_GroupQuery.cs
@@ -0,0 +1,74 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OrmTest
+{
+ internal class _7_GroupQuery
+ {
+ public static void Init()
+ {
+ var db = DbHelper.GetNewDb();
+ List students = new List
+ {
+ new Student { Id = 1, Name = "Alice", Age = 20 },
+ new Student { Id = 2, Name = "Bob", Age = 22 },
+ new Student { Id = 3, Name = "Alice", Age = 21 },
+ new Student { Id = 4, Name = "Charlie", Age = 19 },
+ new Student { Id = 5, Name = "Bob", Age = 20 }
+ };
+
+ // 初始化数据库表结构,如果表不存在则创建 (Initialize database table structure; create if not exists)
+ db.CodeFirst.InitTables();
+
+ // 清空指定表中的所有数据 (Truncate all data in the specified table)
+ db.DbMaintenance.TruncateTable();
+
+ //插入记录(Insert datas)
+ db.Insertable(students).ExecuteCommand();
+
+ // 分组查询示例 (Grouping Query Example)
+ var groupedStudents = db.Queryable()
+ .GroupBy(s => s.Name)
+ .Select(g => new
+ {
+ Name = g.Name, // 学生姓名 (Student Name)
+ Count = SqlFunc.AggregateCount(g.Id), // 学生数量 (Count of Students)
+ AverageAge = SqlFunc.AggregateAvg(g.Age), // 平均年龄 (Average Age)
+ MaxAge = SqlFunc.AggregateMax(g.Age), // 最大年龄 (Maximum Age)
+ MinAge = SqlFunc.AggregateMin(g.Age) // 最小年龄 (Minimum Age)
+ })
+ .ToList();
+
+
+ // 去重查询示例 (Distinct Query Example)
+ var distinctNames = students.Select(s => s.Name).Distinct().ToList();
+
+
+ // 分组取第一条记录示例 (Group First Record Example)
+ var groupFirstRecord = db.Queryable()
+ .Select(g => new
+ {
+ index = SqlFunc.RowNumber(SqlFunc.Desc(g.Id), g.Name),
+ Id = g.Id,
+ Name = g.Name,
+ Age =g.Age
+ })
+ .MergeTable()
+ .Where(it => it.index == 1)
+ .ToList();
+ }
+
+ [SqlSugar.SugarTable("Student07")]
+ public class Student
+ {
+ [SqlSugar.SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; } // 学生ID (Student ID)
+ public string Name { get; set; } // 学生姓名 (Student Name)
+ public int Age { get; set; } // 学生年龄 (Student Age)
+ }
+ }
+}
diff --git a/Src/Asp.NetCore2/DuckDBTest/8_Insert.cs b/Src/Asp.NetCore2/DuckDBTest/8_Insert.cs
new file mode 100644
index 000000000..591a435f9
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/8_Insert.cs
@@ -0,0 +1,66 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Data.Common;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OrmTest
+{
+ internal class _8_Insert
+ {
+ public static void Init()
+ {
+ var db = DbHelper.GetNewDb();
+
+ // 初始化实体表格(Initialize entity tables)
+ db.CodeFirst.InitTables();
+
+ // Use Case 1: 返回插入行数(Return the number of inserted rows)
+ var rowCount = db.Insertable(new StudentWithIdentity() { Name = "name" }).ExecuteCommand();
+
+ // Use Case 2: 插入数据并返回自增列(Insert data and return the auto-incremented column)
+ var identity = db.Insertable(new StudentWithIdentity() { Name = "name2" }).ExecuteReturnIdentity();
+
+ // Use Case 3: 返回雪花ID(Return the snowflake ID)
+ var snowflakeId = db.Insertable(new StudentWithSnowflake() { Name = "name" }).ExecuteReturnSnowflakeId();
+
+ // Use Case 4: 强制设置表名别名(Forcefully set table name alias)
+ db.Insertable(new StudentWithIdentity() { Name = "name2" }).AS("StudentWithIdentity").ExecuteCommand();
+
+ // Use Case 5: 批量插入实体(非参数化插入)(Batch insert entities (non-parameterized))
+ var list = db.Queryable().Take(2).ToList();
+ db.Insertable(list).ExecuteCommand();
+ db.Insertable(list).PageSize(1000).ExecuteCommand();
+
+ // Use Case 6: 参数化内部分页插入(Parameterized internal pagination insert)
+ db.Insertable(list).UseParameter().ExecuteCommand();
+
+ // Use Case 7: 大数据写入(示例代码,请根据实际情况调整)(Bulk data insertion - Example code, adjust based on actual scenario)
+ var listLong = new List() {
+ new StudentWithSnowflake() { Name = "name",Id=SnowFlakeSingle.Instance.NextId() },
+ new StudentWithSnowflake() { Name = "name",Id=SnowFlakeSingle.Instance.NextId()}
+ };
+ db.Fastest().BulkCopy(listLong);
+ }
+
+ // 实体类:带自增主键(Entity class: With auto-increment primary key)
+ [SugarTable("StudentWithIdentity08")]
+ public class StudentWithIdentity
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+
+ // 实体类:带雪花主键(Entity class: With snowflake primary key)
+ [SugarTable("StudentWithSnowflake08")]
+ public class StudentWithSnowflake
+ {
+ [SugarColumn(IsPrimaryKey = true)]
+ public long Id { get; set; }
+ public string Name { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/9_Update.cs b/Src/Asp.NetCore2/DuckDBTest/9_Update.cs
new file mode 100644
index 000000000..dc4d0349e
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/9_Update.cs
@@ -0,0 +1,88 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static OrmTest._8_Insert;
+
+namespace OrmTest
+{
+ internal class _9_Update
+ {
+ ///
+ /// 初始化更新方法(Initialize update methods)
+ ///
+ internal static void Init()
+ {
+ var db = DbHelper.GetNewDb();
+
+ // 初始化实体表格(Initialize entity tables)
+ db.CodeFirst.InitTables();
+
+ // 创建一个需要更新的实体对象(Create an entity object to be updated)
+ var updateObj = new StudentWithSnowflake() { Id = 1, Name = "order1" };
+
+ // 创建需要批量更新的实体对象列表(Create a list of entity objects to be updated in bulk)
+ var updateObjs = new List {
+ new StudentWithSnowflake() { Id = 11, Name = "order11", Date=DateTime.Now },
+ new StudentWithSnowflake() { Id = 12, Name = "order12", Date=DateTime.Now }
+ };
+
+ /***************************根据实体更新 (Update based on entity)***************************/
+
+ // 更新单个实体对象(Update a single entity object)
+ var result = db.Updateable(updateObj).ExecuteCommand();
+
+ // 批量更新实体对象列表(Update a list of entity objects in bulk)
+ var result20 = db.Updateable(updateObjs).ExecuteCommand();
+ var result21 = db.Updateable(updateObjs).PageSize(500).ExecuteCommand();
+
+ // 更新实体对象,忽略指定列(Update entity object, ignoring specific columns)
+ var result3 = db.Updateable(updateObj).IgnoreColumns(it => new { it.Remark }).ExecuteCommand();
+
+ // 更新实体对象的指定列(Update specific columns of the entity object)
+ var result4 = db.Updateable(updateObj).UpdateColumns(it => new { it.Name, it.Date }).ExecuteCommand();
+
+ // 如果没有主键,按照指定列更新实体对象(If there is no primary key, update entity object based on specified columns)
+ var result5 = db.Updateable(updateObj).WhereColumns(it => new { it.Id }).ExecuteCommand();
+
+ // 如果字段值为NULL,不进行更新(Do not update columns with NULL values)
+ var result6 = db.Updateable(updateObj).IgnoreNullColumns().ExecuteCommand();
+
+ // 忽略为NULL和默认值的列进行更新(Ignore columns with NULL and default values during update)
+ var result7 = db.Updateable(updateObj)
+ .IgnoreColumns(ignoreAllNullColumns: true, ignoreAllDefaultValue:true)
+ .ExecuteCommand();
+
+ // 使用最快的方式批量更新实体对象列表(Bulk update a list of entity objects using the fastest method)
+ var result8 = db.Fastest().BulkUpdate(updateObjs);
+
+ /***************************表达式更新 (Expression Update)***************************/
+
+ // 使用表达式更新实体对象的指定列(Update specific columns of the entity object using expressions)
+ var result71 = db.Updateable()
+ .SetColumns(it => new StudentWithSnowflake() { Name = "a", Date = DateTime.Now })
+ .Where(it => it.Id == 11)
+ .ExecuteCommand();
+
+ // 使用表达式更新实体对象的指定列(Update specific columns of the entity object using expressions)
+ var result81 = db.Updateable()
+ .SetColumns(it => it.Name == "Name" + "1")
+ .Where(it => it.Id == 1)
+ .ExecuteCommand();
+ }
+
+ // 实体类:带雪花主键(Entity class: With snowflake primary key)
+ [SugarTable("StudentWithSnowflake09")]
+ public class StudentWithSnowflake
+ {
+ [SugarColumn(IsPrimaryKey = true)]
+ public long Id { get; set; }
+ public string Name { get; set; }
+ public DateTime Date { get; set; }
+ [SugarColumn(IsNullable = true)]
+ public string Remark { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/DuckDBTest.csproj b/Src/Asp.NetCore2/DuckDBTest/DuckDBTest.csproj
new file mode 100644
index 000000000..6a2ac3e66
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/DuckDBTest.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net6.0
+ enable
+ enable
+ Exe
+
+
+
+
+
+
+
diff --git a/Src/Asp.NetCore2/DuckDBTest/Program.cs b/Src/Asp.NetCore2/DuckDBTest/Program.cs
new file mode 100644
index 000000000..81a0814d1
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/Program.cs
@@ -0,0 +1,40 @@
+using SqlSugar;
+
+Console.Read();
+///
+/// Helper class for database operations
+/// 数据库操作的辅助类
+///
+public class DbHelper
+{
+ ///
+ /// Database connection string
+ /// 数据库连接字符串
+ ///
+ public readonly static string Connection = "DataSource = train_services.db";
+
+ ///
+ /// Get a new SqlSugarClient instance with specific configurations
+ /// 获取具有特定配置的新 SqlSugarClient 实例
+ ///
+ /// SqlSugarClient instance
+ public static SqlSugarClient GetNewDb()
+ {
+ var db = new SqlSugarClient(new ConnectionConfig()
+ {
+ IsAutoCloseConnection = true,
+ DbType = DbType.DuckDB,
+ ConnectionString = Connection,
+ LanguageType = LanguageType.Default//Set language
+
+ },
+ it => {
+ // Logging SQL statements and parameters before execution
+ // 在执行前记录 SQL 语句和参数
+ it.Aop.OnLogExecuting = (sql, para) =>
+ {
+ Console.WriteLine(UtilMethods.GetNativeSql(sql, para));
+ };
+ });
+ return db;
+ }
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/a1_Delete.cs b/Src/Asp.NetCore2/DuckDBTest/a1_Delete.cs
new file mode 100644
index 000000000..03b37ce43
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/a1_Delete.cs
@@ -0,0 +1,186 @@
+using SqlSugar;
+using System.Collections.Generic;
+
+namespace OrmTest
+{
+ internal class _a1_Delete
+ {
+ ///
+ /// 初始化删除操作的示例方法。
+ /// Initializes example methods for delete operations.
+ ///
+ internal static void Init()
+ {
+ // 获取新的数据库连接对象
+ // Get a new database connection object
+ var db = DbHelper.GetNewDb();
+
+ db.CodeFirst.InitTables();
+
+ // 调用各个删除操作的示例方法
+ // Calling example methods for various delete operations
+ DeleteSingleEntity(db);
+
+ // 批量删除实体的示例方法
+ // Example method for deleting entities in batch
+ DeleteBatchEntities(db);
+
+ // 批量删除并分页的示例方法
+ // Example method for deleting entities in batch with paging
+ DeleteBatchEntitiesWithPaging(db);
+
+ // 调用无主键实体删除的示例方法
+ // Calling example method for deleting entities without primary key
+ DeleteEntitiesWithoutPrimaryKey(db);
+
+ // 调用根据主键删除实体的示例方法
+ // Calling example method for deleting entity by primary key
+ DeleteEntityByPrimaryKey(1, db);
+
+ // 调用根据主键数组批量删除实体的示例方法
+ // Calling example method for deleting entities by primary key array
+ DeleteEntitiesByPrimaryKeyArray(db);
+
+ // 调用根据表达式删除实体的示例方法
+ // Calling example method for deleting entities by expression
+ DeleteEntitiesByExpression(db);
+
+ // 调用联表删除实体的示例方法
+ // Calling example method for deleting entities with join
+ DeleteEntitiesWithJoin(db);
+ }
+
+ ///
+ /// 删除单个实体的示例方法。
+ /// Example method for deleting a single entity.
+ ///
+ internal static void DeleteSingleEntity(ISqlSugarClient db)
+ {
+ // 删除指定 Id 的学生实体
+ // Delete the student entity with the specified Id
+ db.Deleteable(new Student() { Id = 1 }).ExecuteCommand();
+ }
+
+ ///
+ /// 批量删除实体的示例方法。
+ /// Example method for deleting entities in batch.
+ ///
+ internal static void DeleteBatchEntities(ISqlSugarClient db)
+ {
+ // 创建学生实体列表
+ // Create a list of student entities
+ List list = new List()
+ {
+ new Student() { Id = 1 }
+ };
+
+ // 批量删除学生实体
+ // Delete student entities in batch
+ db.Deleteable(list).ExecuteCommand();
+ }
+
+ ///
+ /// 批量删除并分页的示例方法。
+ /// Example method for deleting entities in batch with paging.
+ ///
+ internal static void DeleteBatchEntitiesWithPaging(ISqlSugarClient db)
+ {
+ // 创建订单实体列表
+ // Create a list of order entities
+ List list = new List();
+
+ // 批量删除订单实体并分页
+ // Delete order entities in batch with paging
+ db.Deleteable(list).PageSize(500).ExecuteCommand();
+ }
+
+ ///
+ /// 无主键实体删除的示例方法。
+ /// Example method for deleting entities without primary key.
+ ///
+ internal static void DeleteEntitiesWithoutPrimaryKey( ISqlSugarClient db)
+ {
+ List orders = new List()
+ {
+ new Order() { Id = 1 },
+ new Order() { Id = 2 }
+ };
+
+ // 根据指定的实体列表的 Id 列进行删除
+ // Delete entities based on the Id column of the specified entity list
+ db.Deleteable().WhereColumns(orders, it => new { it.Id }).ExecuteCommand();
+ }
+
+ ///
+ /// 根据主键删除实体的示例方法。
+ /// Example method for deleting an entity by primary key.
+ ///
+ internal static void DeleteEntityByPrimaryKey(int id, ISqlSugarClient db)
+ {
+ // 根据指定的 Id 删除学生实体
+ // Delete the student entity with the specified Id
+ db.Deleteable().In(id).ExecuteCommand();
+ }
+
+ ///
+ /// 根据主键数组批量删除实体的示例方法。
+ /// Example method for deleting entities by primary key array.
+ ///
+ internal static void DeleteEntitiesByPrimaryKeyArray(ISqlSugarClient db)
+ {
+ // 定义主键数组
+ // Define an array of primary keys
+ int[] ids = { 1, 2 };
+
+ // 根据指定的 Id 数组批量删除学生实体
+ // Delete student entities in batch based on the specified Id array
+ db.Deleteable().In(ids).ExecuteCommand();
+ }
+
+ ///
+ /// 根据表达式删除实体的示例方法。
+ /// Example method for deleting entities by expression.
+ ///
+ internal static void DeleteEntitiesByExpression(ISqlSugarClient db)
+ {
+ // 根据指定的表达式删除学生实体
+ // Delete the student entity based on the specified expression
+ db.Deleteable().Where(it => it.Id == 1).ExecuteCommand();
+ }
+
+ ///
+ /// 联表删除实体的示例方法。
+ /// Example method for deleting entities with join.
+ ///
+ internal static void DeleteEntitiesWithJoin(ISqlSugarClient db)
+ {
+ // 联表删除学生实体
+ // Delete student entities with join
+ db.Deleteable()
+ .Where(p => SqlFunc.Subqueryable().Where(s => s.Id == p.SchoolId).Any())
+ .ExecuteCommand();
+ }
+
+ [SugarTable("Students_a1")]
+ public class Student
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] // 主键
+ public int Id { get; set; }
+
+ public string Name { get; set; }
+
+ public int SchoolId { get; set; }
+ }
+
+ [SugarTable("Orders_a2")]
+ public class Order
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] // 主键
+ public int Id { get; set; }
+
+ public string OrderNumber { get; set; }
+
+ public decimal Amount { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/a2_Sql.cs b/Src/Asp.NetCore2/DuckDBTest/a2_Sql.cs
new file mode 100644
index 000000000..ec9efb782
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/a2_Sql.cs
@@ -0,0 +1,74 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+
+namespace OrmTest
+{
+ internal class _a2_Sql
+ {
+ ///
+ /// 初始化 SQL 操作的示例方法。
+ /// Initializes example methods for SQL operations.
+ ///
+ internal static void Init()
+ {
+ // 获取新的数据库连接对象
+ // Get a new database connection object
+ var db = DbHelper.GetNewDb();
+
+ // CodeFirst 初始化 ClassA 表
+ // CodeFirst initializes the ClassA table
+ db.CodeFirst.InitTables();
+ db.Insertable(new ClassA() { Name = Guid.NewGuid().ToString("N") }).ExecuteCommand();
+
+ // 1. 无参数查询 DataTable
+ // 1. Query DataTable without parameters
+ var dt1 = db.Ado.GetDataTable("SELECT * FROM Table_a2");
+
+ // 2. 带参数查询 DataTable(简化用法)
+ // 2. Query DataTable with parameters (simplified usage)
+ var dt2 = db.Ado.GetDataTable("SELECT * FROM Table_a2 WHERE id=@id AND name LIKE @name",
+ new { id = 1, name = "%Jack%" });
+
+ // 3. 带参数查询 DataTable(复杂用法)
+ // 3. Query DataTable with parameters (complex usage)
+ var parameters = new List
+ {
+ new SugarParameter("@id", 1),
+ new SugarParameter("@name", "%Jack%",System.Data.DbType.AnsiString)//DbType
+ };
+ var dt3 = db.Ado.GetDataTable("SELECT * FROM Table_a2 WHERE id=@id AND name LIKE @name", parameters);
+
+ // 4. 带参数查询 DataTable(结合用法)
+ // 4. Query DataTable with parameters (combined usage)
+ var dynamicParameters = db.Ado.GetParameters(new { p = 1, p2 = "A" });
+ var dt4 = db.Ado.GetDataTable("SELECT * FROM Table_a2 WHERE id=@p AND name=@p2", dynamicParameters);
+
+ // 原生 SQL 使用实体进行查询
+ // Native SQL query using an entity
+ List entities = db.Ado.SqlQuery("SELECT * FROM Table_a2");
+ List entities2 = db.Ado.SqlQuery("SELECT * FROM Table_a2 WHERE ID>@ID",new { ID=1});
+
+ // 原生 SQL 使用匿名对象进行查询
+ // Native SQL query using an anonymous object
+ List anonymousObjects = db.Ado.SqlQuery("SELECT * FROM Table_a2");
+
+ // 执行 SQL 命令(插入、更新、删除操作)
+ // Execute SQL commands (insert, update, delete operations)
+ db.Ado.ExecuteCommand("INSERT INTO Table_a2 (name) VALUES ( 'New Record')");
+ }
+
+ ///
+ /// 示例实体类。
+ /// Example entity class.
+ ///
+ [SugarTable("Table_a2")]
+ public class ClassA
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+
+ public string Name { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/a3_Merge.cs b/Src/Asp.NetCore2/DuckDBTest/a3_Merge.cs
new file mode 100644
index 000000000..561dd248c
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/a3_Merge.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OrmTest
+{
+ internal class _a3_Merge
+ {
+ // 中文备注:初始化方法(用于大数据处理)
+ // English Comment: Initialization method (for big data processing)
+ internal static void Init()
+ {
+ var db = DbHelper.GetNewDb();
+ //建表
+ //Create table
+ db.CodeFirst.InitTables();
+ var list = new List() { new Order() { Name = "jack" } };
+
+ // 中文备注:执行插入或更新操作
+ // English Comment: Perform insert or update operation
+ db.Storageable(list).ExecuteCommand();
+
+ // 中文备注:分页执行插入或更新操作,每页1000条记录
+ // English Comment: Perform insert or update operation with paging, 1000 records per page
+ db.Storageable(list).PageSize(1000).ExecuteCommand();
+
+ // 中文备注:带异常处理的分页插入或更新操作,每页1000条记录
+ // English Comment: Perform insert or update operation with exception handling and paging, 1000 records per page
+ db.Storageable(list).PageSize(1000, exrows => { }).ExecuteCommand();
+
+ // 中文备注:使用Fastest方式批量合并数据(用于大数据处理)
+ // English Comment: Merge data using Fastest method (for big data processing)
+ db.Fastest().BulkMerge(list);
+
+ // 中文备注:分页使用Fastest方式批量合并数据,每页100000条记录(用于大数据处理)
+ // English Comment: Merge data using Fastest method with paging, 100000 records per page (for big data processing)
+ db.Fastest().PageSize(100000).BulkMerge(list);
+ }
+
+ [SqlSugar.SugarTable("Order_a3")]
+ public class Order
+ {
+ [SqlSugar.SugarColumn(IsPrimaryKey =true,IsIdentity =true)]
+ public int Id { get; set; }
+ public string Name { get; set; }
+ // 其他属性
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/a4_SplitTable.cs b/Src/Asp.NetCore2/DuckDBTest/a4_SplitTable.cs
new file mode 100644
index 000000000..dca9e4542
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/a4_SplitTable.cs
@@ -0,0 +1,66 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OrmTest
+{
+ internal class _a4_SplitTable
+ {
+ // Method for initialization and testing of split tables
+ // 用于初始化和测试分表的方法
+ public static void Init()
+ {
+ // Obtain a new instance of SqlSugarClient
+ // 获取 SqlSugarClient 的新实例
+ SqlSugarClient db = DbHelper.GetNewDb();
+
+
+ // Entities change the synchronization table structure
+ // 实体变化同步表结构
+ db.CodeFirst.SplitTables().InitTables();
+
+ // Insert records into the split table and create table
+ // 向分表插入记录并创建表
+ db.Insertable(new SplitTableDemo() { Name = "jack", Time = DateTime.Now }).SplitTable().ExecuteCommand();
+ db.Insertable(new SplitTableDemo() { Name = "jack2", Time = DateTime.Now.AddDays(-11) }).SplitTable().ExecuteCommand();
+
+ // Query records from the split table within a specified date range
+ // 在指定日期范围内从分表查询记录
+ var list = db.Queryable()
+ .Where(it=>it.Name!=null)
+ .SplitTable(DateTime.Now.Date.AddYears(-1), DateTime.Now)
+ .ToList();
+
+ // Update records from the split table
+ // 从分表更新记录
+ var updateList = list.Take(2).ToList();
+ db.Updateable(updateList).SplitTable().ExecuteCommand();
+
+ // Delete records from the split table
+ // 从分表删除记录
+ db.Deleteable(updateList).SplitTable().ExecuteCommand();
+ }
+
+ // Entity class representing the split table
+ // 代表分表的实体类
+ [SplitTable(SplitType.Day)] // Specify the split type as "Day"
+ // 指定分表类型为“Day”
+ [SqlSugar.SugarTable("SplitTableDemo_{year}{month}{day}")] // Specify the table name pattern
+ // 指定表名模式
+ public class SplitTableDemo
+ {
+ [SugarColumn(IsPrimaryKey = true)] // Specify primary key
+ // 指定主键
+ public Guid Pk { get; set; }
+ public string Name { get; set; }
+
+ [SugarColumn(IsNullable = true)]
+ [SplitField] // Mark the field as a split field
+ // 将字段标记为分表字段
+ public DateTime Time { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/a5_GridSave.cs b/Src/Asp.NetCore2/DuckDBTest/a5_GridSave.cs
new file mode 100644
index 000000000..4ee26ac92
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/a5_GridSave.cs
@@ -0,0 +1,81 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OrmTest
+{
+ internal class _a5_GridSave
+ {
+ public static void Init()
+ {
+ // Get a new database connection
+ // 获取一个新的数据库连接
+ SqlSugarClient db = DbHelper.GetNewDb();
+
+ // Initialize tables using CodeFirst
+ // 使用 CodeFirst 初始化表
+ db.CodeFirst.InitTables();
+
+ // Clear table data
+ // 清空表数据
+ db.DbMaintenance.TruncateTable();
+
+ // Insert two student records
+ // 插入两条学生记录
+ db.Insertable(new List() {
+ new Student() {Name= "jack",CreateTime=DateTime.Now},
+ new Student() {Name= "tom",CreateTime=DateTime.Now}
+ }).ExecuteReturnIdentity();
+
+ // Query all student records
+ // 查询所有学生记录
+ List getAll = db.Queryable().ToList();
+
+
+
+ // Enable entity tracking for the list 'getAll'
+ // 启用对列表 'getAll' 的实体跟踪
+ db.Tracking(getAll);
+
+
+
+
+ // Remove the first record
+ // 移除第一条记录
+ getAll.RemoveAt(0);
+
+ // Modify the name of the last record
+ // 修改最后一条记录的姓名
+ getAll[getAll.Count - 1].Name += "_Update";
+
+ // Add a new record
+ // 添加新记录
+ getAll.Add(new Student { Name = "NewRecord" });
+
+
+
+
+
+ // Execute GridSave operation
+ // 执行 GridSave 操作
+ db.GridSave(getAll).ExecuteCommand();
+
+ // Query all students again
+ // 再次查询所有学生
+ var list = db.Queryable().ToList();
+ }
+
+ // Define the entity class 定义实体类
+ [SugarTable("SaveTable_a5")]
+ public class Student
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public DateTime CreateTime { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/a6_SqlPage.cs b/Src/Asp.NetCore2/DuckDBTest/a6_SqlPage.cs
new file mode 100644
index 000000000..47a67aaef
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/a6_SqlPage.cs
@@ -0,0 +1,59 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OrmTest
+{
+ internal class _a6_SqlPage
+ {
+ ///
+ ///
+ /// Initializes an example method for SQL paging operations.
+ /// 初始化 SQL 分页操作的示例方法。
+ ///
+ internal static void Init()
+ {
+ // Get a new database connection object
+ // 获取新的数据库连接对象
+ var db = DbHelper.GetNewDb();
+
+ // CodeFirst initializes the ClassA table
+ // CodeFirst 初始化 ClassA 表
+ db.CodeFirst.InitTables();
+ for (int i = 0; i < 16; i++)
+ {
+ db.Insertable(new ClassA() { Name = Guid.NewGuid().ToString("N") }).ExecuteCommand();
+ }
+
+
+ // Query data using paging and get the total count
+ // 使用分页查询数据,并获取总记录数
+ int count = 0;
+ var list = db.SqlQueryable("select * from Table_a6").ToPageList(1, 5, ref count);
+
+
+
+ // Asynchronously query data using paging and get the total count
+ // 使用异步方式分页查询数据,并获取总记录数
+ RefAsync countAsync = 0;
+ var listAsync = db.SqlQueryable("select * from Table_a6").ToPageListAsync(1, 5, countAsync).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Example entity class.
+ /// 示例实体类。
+ ///
+ [SugarTable("Table_a6")]
+ public class ClassA
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+
+ public string Name { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/a7_JsonType.cs b/Src/Asp.NetCore2/DuckDBTest/a7_JsonType.cs
new file mode 100644
index 000000000..fe67d3f3e
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/a7_JsonType.cs
@@ -0,0 +1,87 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace OrmTest
+{
+ internal class _a7_JsonType
+ {
+ ///
+ /// Demonstrates JSON operations with SqlSugar.
+ /// 展示了在 SqlSugar 中进行 JSON 操作的示例。
+ ///
+ internal static void Init()
+ {
+ // Get a new database connection object
+ // 获取一个新的数据库连接对象
+ var db = DbHelper.GetNewDb();
+
+ // Create table
+ // 创建表
+ db.CodeFirst.InitTables();
+
+ // Insert a record with a JSON property
+ // 插入一条包含 JSON 属性的记录
+ db.Insertable(new UnitJsonTest()
+ {
+ Name = "json1",
+ Order = new Order { Id = 1, Name = "order1" }
+ }).ExecuteCommand();
+
+ // Query all records from the table
+ // 查询表中的所有记录
+ var list = db.Queryable().ToList();
+
+ //Sqlfunc.JsonXXX
+ var list2=db.Queryable()
+ .Select(it => new
+ {
+ id=it.Id,
+ jsonname=SqlFunc.JsonField(it.Order,"Name")
+ })
+ .ToList();
+
+ var list3=db.Queryable().Select(it => new
+ {
+
+ Order1 = new UnitJsonTest()
+ {
+ Id=it.Id,
+ Order = it.Order
+ }
+ }).ToList();
+
+ if (list3.First().Order1.Order == null|| list3.First().Order1.Order.Id==0)
+ {
+ throw new Exception("unit error");
+ }
+ }
+
+ ///
+ /// Represents a class with a JSON property.
+ /// 表示一个包含 JSON 属性的类。
+ ///
+ [SugarTable("UnitJsonTest_a7")]
+ public class UnitJsonTest
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+
+ [SugarColumn(IsJson = true)]
+ public Order Order { get; set; }
+
+ public string Name { get; set; }
+ }
+
+ ///
+ /// Represents an order entity.
+ /// 表示订单实体。
+ ///
+ public class Order
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/DuckDBTest/a8_SelectReturnType.cs b/Src/Asp.NetCore2/DuckDBTest/a8_SelectReturnType.cs
new file mode 100644
index 000000000..4e7e67af1
--- /dev/null
+++ b/Src/Asp.NetCore2/DuckDBTest/a8_SelectReturnType.cs
@@ -0,0 +1,68 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+
+namespace OrmTest
+{
+ internal class _a8_SelectReturnType
+ {
+ internal static void Init()
+ {
+ var db = DbHelper.GetNewDb();
+
+ //Create table
+ //建表
+ db.CodeFirst.InitTables();
+ //init data
+ db.Insertable(new Student() { CreateTime = DateTime.Now, Name = "aa" }).ExecuteCommand();
+
+
+ // 返回匿名对象 (Return anonymous objects)
+ var dynamicList = db.Queryable().Select().ToList();
+ // SELECT * FROM Student_a8
+
+ // 手动:返回匿名集合,支持跨程序集 (Manually: Return an anonymous collection, supporting cross-assembly)
+ List dynamicListCrossAssembly = db.Queryable().Select(it => (dynamic)new { id = it.Id }).ToList();
+ // SELECT id AS id FROM Student_a8
+
+ // 手动:返回匿名集合,不能跨程序集 (Manually: Return an anonymous collection, within the same assembly)
+ var dynamicListWithinAssembly = db.Queryable().Select(it => new { id = it.Id }).ToList();
+ // SELECT id AS id FROM Student_a8
+
+ // 手动:返回类集合-手动 (Manually: Return a class collection manually)
+ List classList = db.Queryable().Select(it => new Student { Id = it.Id }).ToList();
+ // SELECT id AS Id FROM Student_a8
+
+ // 自动返回DTO集合: 请升级至 5.1.3.2 版本 (Automatically return DTO collections: Upgrade to version 5.1.3.2)
+ var listDto = db.Queryable().Select().ToList();
+
+ // 自动返回DTO: 请升级至 5.1.3.35 版本 (Automatically return DTO: Upgrade to version 5.1.3.35)
+ var listDtoAutoMap = db.Queryable()
+ .Select(it => new StudentDto
+ {
+ AppendColumn = 100 // 手动指定一列在自动映射 (Manually specify a column in automatic mapping)
+ },
+ true) // true 表示开启自动映射 (true indicates enabling automatic mapping)
+ .ToList();
+ }
+
+ // 学生表的实体类 (Entity class for the Student table)
+ [SugarTable("Student_a8")]
+ public class Student
+ {
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public DateTime CreateTime { get; set; }
+ }
+
+ // DTO 数据传输对象 (DTO - Data Transfer Object)
+ public class StudentDto
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public DateTime CreateTime { get; set; }
+ public int AppendColumn { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/CodeFirst/DuckDBCodeFirst.cs b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/CodeFirst/DuckDBCodeFirst.cs
new file mode 100644
index 000000000..0ea3e0c02
--- /dev/null
+++ b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/CodeFirst/DuckDBCodeFirst.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace SqlSugar.DuckDB
+{
+ public class DuckDBCodeFirst : CodeFirstProvider
+ {
+ protected override void ExistLogicEnd(List dbColumns)
+ {
+ foreach (EntityColumnInfo column in dbColumns)
+ {
+ if (column.DefaultValue != null)
+ {
+ this.Context.DbMaintenance.AddDefaultValue(column.DbTableName,column.DbColumnName,column.DefaultValue.ToSqlValue());
+ }
+ }
+ }
+ public override void NoExistLogic(EntityInfo entityInfo)
+ {
+ var tableName = GetTableName(entityInfo);
+ //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Use Code First ,The primary key must not exceed 1");
+ List columns = new List();
+ if (entityInfo.Columns.HasValue())
+ {
+ foreach (var item in entityInfo.Columns.Where(it=>it.IsIgnore==false))
+ {
+ DbColumnInfo dbColumnInfo = this.EntityColumnToDbColumn(entityInfo, tableName, item);
+ columns.Add(dbColumnInfo);
+ }
+ if (entityInfo.IsCreateTableFiledSort)
+ {
+ columns = columns.OrderBy(c => c.CreateTableFieldSort).ToList();
+ }
+ }
+ columns = columns.OrderBy(it => it.IsPrimarykey ? 0 : 1).ToList();
+ this.Context.DbMaintenance.CreateTable(tableName, columns,true);
+ }
+ protected override DbColumnInfo EntityColumnToDbColumn(EntityInfo entityInfo, string tableName, EntityColumnInfo item)
+ {
+ var propertyType = UtilMethods.GetUnderType(item.PropertyInfo);
+ var result = new DbColumnInfo()
+ {
+ TableId = entityInfo.Columns.IndexOf(item),
+ DbColumnName = item.DbColumnName.HasValue() ? item.DbColumnName : item.PropertyName,
+ IsPrimarykey = item.IsPrimarykey,
+ IsIdentity = item.IsIdentity,
+ TableName = tableName,
+ IsNullable = item.IsNullable,
+ DefaultValue = item.DefaultValue,
+ ColumnDescription = item.ColumnDescription,
+ Length = item.Length,
+ CreateTableFieldSort = item.CreateTableFieldSort
+ };
+ if (propertyType == UtilConstants.DecType)
+ {
+ result.Scale = item.DecimalDigits;
+ result.DecimalDigits = item.DecimalDigits;
+ }
+ GetDbType(item, propertyType, result);
+ if (result.DataType.Equals("varchar", StringComparison.CurrentCultureIgnoreCase) && result.Length == 0)
+ {
+ result.Length = 1;
+ }
+ return result;
+ }
+
+ protected override void ConvertColumns(List dbColumns)
+ {
+ foreach (var item in dbColumns)
+ {
+ if (item.DataType == "DateTime")
+ {
+ item.Length = 0;
+ }
+ }
+ }
+
+ protected override void ChangeKey(EntityInfo entityInfo, string tableName, EntityColumnInfo item)
+ {
+ this.Context.DbMaintenance.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item));
+ if (!item.IsPrimarykey)
+ this.Context.DbMaintenance.DropConstraint(tableName,null);
+ if (item.IsPrimarykey)
+ this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName);
+ }
+
+ }
+}
diff --git a/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/DbBind/DuckDBDbBind.cs b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/DbBind/DuckDBDbBind.cs
new file mode 100644
index 000000000..c3b997334
--- /dev/null
+++ b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/DbBind/DuckDBDbBind.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace SqlSugar.DuckDB
+{
+ public class DuckDBDbBind : DbBindProvider
+ {
+ public override string GetDbTypeName(string csharpTypeName)
+ {
+ if (csharpTypeName == UtilConstants.ByteArrayType.Name)
+ return "bytea";
+ if (csharpTypeName.ToLower() == "int32")
+ csharpTypeName = "int";
+ if (csharpTypeName.ToLower() == "int16")
+ csharpTypeName = "short";
+ if (csharpTypeName.ToLower() == "int64")
+ csharpTypeName = "long";
+ if (csharpTypeName.ToLower().IsIn("boolean", "bool"))
+ csharpTypeName = "bool";
+ if (csharpTypeName == "DateTimeOffset")
+ csharpTypeName = "DateTime";
+ var mappings = this.MappingTypes.Where(it => it.Value.ToString().Equals(csharpTypeName, StringComparison.CurrentCultureIgnoreCase)).ToList();
+ if (mappings != null && mappings.Count > 0)
+ return mappings.First().Key;
+ else
+ return "varchar";
+ }
+ public override string GetPropertyTypeName(string dbTypeName)
+ {
+ dbTypeName = dbTypeName.ToLower();
+ var propertyTypes = MappingTypes.Where(it => it.Value.ToString().ToLower() == dbTypeName || it.Key.ToLower() == dbTypeName);
+ if (propertyTypes == null)
+ {
+ return "other";
+ }
+ else if (dbTypeName == "xml" || dbTypeName == "string"|| dbTypeName == "jsonb"|| dbTypeName == "json")
+ {
+ return "string";
+ }else if (dbTypeName == "bpchar")//数据库char datatype 查询出来的时候是 bpchar
+ {
+ return "char";
+ }
+ if (dbTypeName == "byte[]")
+ {
+ return "byte[]";
+ }
+ else if (propertyTypes == null || propertyTypes.Count() == 0)
+ {
+ if (dbTypeName.StartsWith("_"))
+ {
+ var dbTypeName2 = dbTypeName.TrimStart('_');
+ return MappingTypes.Where(it => it.Value.ToString().ToLower() == dbTypeName2 || it.Key.ToLower() == dbTypeName2).Select(it => it.Value + "[]").First();
+ }
+ Check.ThrowNotSupportedException(string.Format(" \"{0}\" Type NotSupported, DbBindProvider.GetPropertyTypeName error.", dbTypeName));
+ return null;
+ }
+ else if (propertyTypes.First().Value == CSharpDataType.byteArray)
+ {
+ return "byte[]";
+ }
+ else
+ {
+ return propertyTypes.First().Value.ToString();
+ }
+ }
+ public override List> MappingTypes
+ {
+ get
+ {
+ var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices;
+ if (extService != null && extService.AppendDataReaderTypeMappings.HasValue())
+ {
+ return extService.AppendDataReaderTypeMappings.Union(MappingTypesConst).ToList();
+ }
+ else
+ {
+ return MappingTypesConst;
+ }
+ }
+ }
+ public static List> MappingTypesConst = new List>(){
+
+ new KeyValuePair("int2",CSharpDataType.@short),
+ new KeyValuePair("int1",CSharpDataType.@byte),
+ new KeyValuePair("smallint",CSharpDataType.@short),
+ new KeyValuePair("int4",CSharpDataType.@int),
+ new KeyValuePair("serial",CSharpDataType.@int),
+ new KeyValuePair("integer",CSharpDataType.@int),
+ new KeyValuePair("int8",CSharpDataType.@long),
+ new KeyValuePair("bigint",CSharpDataType.@long),
+ new KeyValuePair("float4",CSharpDataType.@float),
+ new KeyValuePair("float4",CSharpDataType.Single),
+ new KeyValuePair("real",CSharpDataType.@float),
+ new KeyValuePair("float8",CSharpDataType.@double),
+ new KeyValuePair("double precision",CSharpDataType.@int),
+ new KeyValuePair("numeric",CSharpDataType.@decimal),
+ new KeyValuePair("decimal",CSharpDataType.@decimal),
+ new KeyValuePair("path",CSharpDataType.@decimal),
+ new KeyValuePair("point",CSharpDataType.@decimal),
+ new KeyValuePair("polygon",CSharpDataType.@decimal),
+
+ new KeyValuePair("boolean",CSharpDataType.@bool),
+ new KeyValuePair("bool",CSharpDataType.@bool),
+ new KeyValuePair("box",CSharpDataType.@bool),
+ new KeyValuePair("bytea",CSharpDataType.byteArray),
+
+ new KeyValuePair("varchar",CSharpDataType.@string),
+ new KeyValuePair("character varying",CSharpDataType.@string),
+ new KeyValuePair("geometry",CSharpDataType.@string),
+ new KeyValuePair("name",CSharpDataType.@string),
+ new KeyValuePair("text",CSharpDataType.@string),
+ new KeyValuePair("char",CSharpDataType.@string),
+ new KeyValuePair("character",CSharpDataType.@string),
+ new KeyValuePair("cidr",CSharpDataType.@string),
+ new KeyValuePair("circle",CSharpDataType.@string),
+ new KeyValuePair("tsquery",CSharpDataType.@string),
+ new KeyValuePair("tsvector",CSharpDataType.@string),
+ new KeyValuePair("txid_snapshot",CSharpDataType.@string),
+ new KeyValuePair("uuid",CSharpDataType.Guid),
+ new KeyValuePair("xml",CSharpDataType.@string),
+ new KeyValuePair("json",CSharpDataType.@string),
+
+ new KeyValuePair("interval",CSharpDataType.@decimal),
+ new KeyValuePair("lseg",CSharpDataType.@decimal),
+ new KeyValuePair("macaddr",CSharpDataType.@decimal),
+ new KeyValuePair("money",CSharpDataType.@decimal),
+ new KeyValuePair("timestamp",CSharpDataType.DateTime),
+ new KeyValuePair("timestamp with time zone",CSharpDataType.DateTime),
+ new KeyValuePair("timestamptz",CSharpDataType.DateTime),
+ new KeyValuePair("timestamp without time zone",CSharpDataType.DateTime),
+ new KeyValuePair("date",CSharpDataType.DateTime),
+ new KeyValuePair("time",CSharpDataType.DateTime),
+ new KeyValuePair("time with time zone",CSharpDataType.DateTime),
+ new KeyValuePair("timetz",CSharpDataType.DateTime),
+ new KeyValuePair("time without time zone",CSharpDataType.DateTime),
+
+ new KeyValuePair("bit",CSharpDataType.byteArray),
+ new KeyValuePair("bit varying",CSharpDataType.byteArray),
+ new KeyValuePair("varbit",CSharpDataType.@byte),
+ new KeyValuePair("time",CSharpDataType.TimeSpan),
+ new KeyValuePair("public.geometry",CSharpDataType.@object),
+ new KeyValuePair("public.geography",CSharpDataType.@object),
+ new KeyValuePair("inet",CSharpDataType.@object)
+ };
+ public override List StringThrow
+ {
+ get
+ {
+ return new List() { "int32", "datetime", "decimal", "double", "byte" };
+ }
+ }
+ }
+}
diff --git a/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/DbFirst/DuckDBDbFirst.cs b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/DbFirst/DuckDBDbFirst.cs
new file mode 100644
index 000000000..b64da4462
--- /dev/null
+++ b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/DbFirst/DuckDBDbFirst.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace SqlSugar.DuckDB
+{
+ public class DuckDBDbFirst : DbFirstProvider
+ {
+ }
+}
diff --git a/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/DbMaintenance/DuckDBDbMaintenance.cs b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/DbMaintenance/DuckDBDbMaintenance.cs
new file mode 100644
index 000000000..1d30e093e
--- /dev/null
+++ b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/DbMaintenance/DuckDBDbMaintenance.cs
@@ -0,0 +1,516 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace SqlSugar.DuckDB
+{
+ public class DuckDBDbMaintenance : DbMaintenanceProvider
+ {
+ #region DML
+ protected override string GetDataBaseSql
+ {
+ get
+ {
+ return "SELECT datname FROM pg_database";
+ }
+ }
+ protected override string GetColumnInfosByTableNameSql
+ {
+ get
+ {
+ string schema = GetSchema();
+ string sql = @"select cast (pclass.oid as int4) as TableId,cast(ptables.tablename as varchar) as TableName,
+ pcolumn.column_name as DbColumnName,pcolumn.udt_name as DataType,
+ CASE WHEN pcolumn.numeric_scale >0 THEN pcolumn.numeric_precision ELSE pcolumn.character_maximum_length END as Length,
+ pcolumn.column_default as DefaultValue,
+ pcolumn.numeric_scale as DecimalDigits,
+ pcolumn.numeric_scale as Scale,
+ col_description(pclass.oid, pcolumn.ordinal_position) as ColumnDescription,
+ case when pkey.colname = pcolumn.column_name
+ then true else false end as IsPrimaryKey,
+ case when pcolumn.column_default like 'nextval%'
+ then true else false end as IsIdentity,
+ case when pcolumn.is_nullable = 'YES'
+ then true else false end as IsNullable
+ from (select * from pg_tables where upper(tablename) = upper('{0}') and schemaname='" + schema + @"') ptables inner join pg_class pclass
+ on ptables.tablename = pclass.relname inner join (SELECT *
+ FROM information_schema.columns
+ ) pcolumn on pcolumn.table_name = ptables.tablename
+ left join (
+ select pg_class.relname,pg_attribute.attname as colname from
+ pg_constraint inner join pg_class
+ on pg_constraint.conrelid = pg_class.oid
+ inner join pg_attribute on pg_attribute.attrelid = pg_class.oid
+ and pg_attribute.attnum = pg_constraint.conkey[1]
+ inner join pg_type on pg_type.oid = pg_attribute.atttypid
+ where pg_constraint.contype='p'
+ ) pkey on pcolumn.table_name = pkey.relname
+ order by table_catalog, table_schema, ordinal_position";
+ return sql;
+ }
+ }
+
+ protected override string GetTableInfoListSql
+ {
+ get
+ {
+ var schema = GetSchema();
+ return @"select cast(relname as varchar) as Name,
+ cast(obj_description(c.oid,'pg_class') as varchar) as Description from pg_class c
+ inner join
+ pg_namespace n on n.oid = c.relnamespace and nspname='" + schema + @"'
+ inner join
+ pg_tables z on z.tablename=c.relname
+ where relkind in('p', 'r') and relname not like 'hg_%' and relname not like 'sql_%' and schemaname='" + schema + "' order by relname";
+ }
+ }
+ protected override string GetViewInfoListSql
+ {
+ get
+ {
+ return @"select cast(relname as varchar) as Name,cast(Description as varchar) from pg_description
+ join pg_class on pg_description.objoid = pg_class.oid
+ where objsubid = 0 and relname in (SELECT viewname from pg_views
+ WHERE schemaname ='"+GetSchema()+"')";
+ }
+ }
+ #endregion
+
+ #region DDL
+ protected override string CreateDataBaseSql
+ {
+ get
+ {
+ return "CREATE DATABASE {0}";
+ }
+ }
+ protected override string AddPrimaryKeySql
+ {
+ get
+ {
+ return "ALTER TABLE {0} ADD PRIMARY KEY({2}) /*{1}*/";
+ }
+ }
+ protected override string AddColumnToTableSql
+ {
+ get
+ {
+ return "ALTER TABLE {0} ADD COLUMN {1} {2}{3} {4} {5} {6}";
+ }
+ }
+ protected override string AlterColumnToTableSql
+ {
+ get
+ {
+ return "alter table {0} ALTER COLUMN {1} {2}{3} {4} {5} {6}";
+ }
+ }
+ protected override string BackupDataBaseSql
+ {
+ get
+ {
+ return "mysqldump.exe {0} -uroot -p > {1} ";
+ }
+ }
+ protected override string CreateTableSql
+ {
+ get
+ {
+ return "CREATE TABLE {0}(\r\n{1} $PrimaryKey)";
+ }
+ }
+ protected override string CreateTableColumn
+ {
+ get
+ {
+ return "{0} {1}{2} {3} {4} {5}";
+ }
+ }
+ protected override string TruncateTableSql
+ {
+ get
+ {
+ return "TRUNCATE TABLE {0}";
+ }
+ }
+ protected override string BackupTableSql
+ {
+ get
+ {
+ return "create table {0} as (select * from {1} limit {2} offset 0)";
+ }
+ }
+ protected override string DropTableSql
+ {
+ get
+ {
+ return "DROP TABLE {0}";
+ }
+ }
+ protected override string DropColumnToTableSql
+ {
+ get
+ {
+ return "ALTER TABLE {0} DROP COLUMN {1}";
+ }
+ }
+ protected override string DropConstraintSql
+ {
+ get
+ {
+ return "ALTER TABLE {0} DROP CONSTRAINT {1}";
+ }
+ }
+ protected override string RenameColumnSql
+ {
+ get
+ {
+ return "ALTER TABLE {0} RENAME {1} TO {2}";
+ }
+ }
+ protected override string AddColumnRemarkSql => "comment on column {1}.{0} is '{2}'";
+
+ protected override string DeleteColumnRemarkSql => "comment on column {1}.{0} is ''";
+
+ protected override string IsAnyColumnRemarkSql { get { throw new NotSupportedException(); } }
+
+ protected override string AddTableRemarkSql => "comment on table {0} is '{1}'";
+
+ protected override string DeleteTableRemarkSql => "comment on table {0} is ''";
+
+ protected override string IsAnyTableRemarkSql { get { throw new NotSupportedException(); } }
+
+ protected override string RenameTableSql => "alter table {0} to {1}";
+
+ protected override string CreateIndexSql
+ {
+ get
+ {
+ return "CREATE {3} INDEX Index_{0}_{2} ON {0} ({1})";
+ }
+ }
+ protected override string AddDefaultValueSql
+ {
+ get
+ {
+ return "ALTER TABLE {0} ALTER COLUMN {1} SET DEFAULT {2}";
+ }
+ }
+ protected override string IsAnyIndexSql
+ {
+ get
+ {
+ return " SELECT count(1) WHERE upper('{0}') IN ( SELECT upper(indexname) FROM pg_indexes )";
+ }
+ }
+ protected override string IsAnyProcedureSql => throw new NotImplementedException();
+ #endregion
+
+ #region Check
+ protected override string CheckSystemTablePermissionsSql
+ {
+ get
+ {
+ return "select 1 from information_schema.columns limit 1 offset 0";
+ }
+ }
+ #endregion
+
+ #region Scattered
+ protected override string CreateTableNull
+ {
+ get
+ {
+ return "DEFAULT NULL";
+ }
+ }
+ protected override string CreateTableNotNull
+ {
+ get
+ {
+ return "NOT NULL";
+ }
+ }
+ protected override string CreateTablePirmaryKey
+ {
+ get
+ {
+ return "PRIMARY KEY";
+ }
+ }
+ protected override string CreateTableIdentity
+ {
+ get
+ {
+ return "serial";
+ }
+ }
+ #endregion
+
+ #region Methods
+ public override List GetIndexList(string tableName)
+ {
+ var sql = $"SELECT indexname, indexdef FROM pg_indexes WHERE upper(tablename) = upper('{tableName}')";
+ return this.Context.Ado.SqlQuery(sql);
+ }
+ public override List GetProcList(string dbName)
+ {
+ var sql = $"SELECT proname FROM pg_proc p JOIN pg_namespace n ON p.pronamespace = n.oid WHERE n.nspname = '{dbName}'";
+ return this.Context.Ado.SqlQuery(sql);
+ }
+ public override bool AddDefaultValue(string tableName, string columnName, string defaultValue)
+ {
+ return base.AddDefaultValue(this.SqlBuilder.GetTranslationTableName(tableName), this.SqlBuilder.GetTranslationTableName(columnName), defaultValue);
+ }
+ public override bool AddColumnRemark(string columnName, string tableName, string description)
+ {
+ tableName = this.SqlBuilder.GetTranslationTableName(tableName);
+ string sql = string.Format(this.AddColumnRemarkSql, this.SqlBuilder.GetTranslationColumnName(columnName.ToLower(isAutoToLowerCodeFirst)), tableName, description);
+ this.Context.Ado.ExecuteCommand(sql);
+ return true;
+ }
+ public override bool AddTableRemark(string tableName, string description)
+ {
+ tableName = this.SqlBuilder.GetTranslationTableName(tableName);
+ return base.AddTableRemark(tableName, description);
+ }
+ public override bool UpdateColumn(string tableName, DbColumnInfo columnInfo)
+ {
+ tableName = this.SqlBuilder.GetTranslationTableName(tableName);
+ var columnName= this.SqlBuilder.GetTranslationColumnName(columnInfo.DbColumnName);
+ string sql = GetUpdateColumnSql(tableName, columnInfo);
+ this.Context.Ado.ExecuteCommand(sql);
+ var isnull = columnInfo.IsNullable?" DROP NOT NULL ": " SET NOT NULL ";
+ this.Context.Ado.ExecuteCommand(string.Format("alter table {0} alter {1} {2}",tableName,columnName, isnull));
+ return true;
+ }
+
+ protected override string GetUpdateColumnSql(string tableName, DbColumnInfo columnInfo)
+ {
+ string columnName = this.SqlBuilder.GetTranslationColumnName(columnInfo.DbColumnName);
+ tableName = this.SqlBuilder.GetTranslationTableName(tableName);
+ string dataSize = GetSize(columnInfo);
+ string dataType = columnInfo.DataType;
+ if (!string.IsNullOrEmpty(dataType))
+ {
+ dataType = " type " + dataType;
+ }
+ string nullType = "";
+ string primaryKey = null;
+ string identity = null;
+ string result = string.Format(this.AlterColumnToTableSql, tableName, columnName, dataType, dataSize, nullType, primaryKey, identity);
+ return result;
+ }
+
+ ///
+ ///by current connection string
+ ///
+ ///
+ ///
+ public override bool CreateDatabase(string databaseName, string databaseDirectory = null)
+ {
+ if (databaseDirectory != null)
+ {
+ if (!FileHelper.IsExistDirectory(databaseDirectory))
+ {
+ FileHelper.CreateDirectory(databaseDirectory);
+ }
+ }
+ // var oldDatabaseName = this.Context.Ado.Connection.Database;
+ //var connection = this.Context.CurrentConnectionConfig.ConnectionString;
+ //connection = connection.Replace(oldDatabaseName, "");
+ if (this.Context.Ado.IsValidConnection())
+ {
+ return true;
+ }
+ var newDb = this.Context.CopyNew();
+ newDb.Ado.Connection.ChangeDatabase("highgo");
+ newDb.Open();
+ if (!GetDataBaseList(newDb).Any(it => it.Equals(databaseName, StringComparison.CurrentCultureIgnoreCase)))
+ {
+ newDb.Ado.ExecuteCommand(string.Format(CreateDataBaseSql, this.SqlBuilder.SqlTranslationLeft+databaseName+this.SqlBuilder.SqlTranslationRight, databaseDirectory));
+ }
+ newDb.Close();
+ return true;
+ }
+ public override bool AddRemark(EntityInfo entity)
+ {
+ var db = this.Context;
+ var columns = entity.Columns.Where(it => it.IsIgnore == false).ToList();
+
+ foreach (var item in columns)
+ {
+ if (item.ColumnDescription != null)
+ {
+ db.DbMaintenance.AddColumnRemark(item.DbColumnName, item.DbTableName, item.ColumnDescription);
+
+ }
+ }
+ //table remak
+ if (entity.TableDescription != null)
+ {
+ db.DbMaintenance.AddTableRemark(entity.DbTableName, entity.TableDescription);
+ }
+ return true;
+ }
+ public override bool CreateTable(string tableName, List columns, bool isCreatePrimaryKey = true)
+ {
+ if (columns.HasValue())
+ {
+ foreach (var item in columns)
+ {
+ if (item.DbColumnName.Equals("GUID", StringComparison.CurrentCultureIgnoreCase) && item.Length == 0)
+ {
+ item.Length = 10;
+ }
+ }
+ }
+ string sql = GetCreateTableSql(tableName, columns);
+ string primaryKeyInfo = null;
+ if (columns.Any(it => it.IsPrimarykey) && isCreatePrimaryKey)
+ {
+ primaryKeyInfo = string.Format(", Primary key({0})", string.Join(",", columns.Where(it => it.IsPrimarykey).Select(it => this.SqlBuilder.GetTranslationColumnName(it.DbColumnName.ToLower(isAutoToLowerCodeFirst)))));
+
+ }
+ sql = sql.Replace("$PrimaryKey", primaryKeyInfo);
+ this.Context.Ado.ExecuteCommand(sql);
+ return true;
+ }
+ protected override string GetCreateTableSql(string tableName, List columns)
+ {
+ List columnArray = new List();
+ Check.Exception(columns.IsNullOrEmpty(), "No columns found ");
+ foreach (var item in columns)
+ {
+ string columnName = item.DbColumnName;
+ string dataType = item.DataType;
+ if (dataType == "varchar" && item.Length == 0)
+ {
+ item.Length = 1;
+ }
+ //if (dataType == "uuid")
+ //{
+ // item.Length = 50;
+ // dataType = "varchar";
+ //}
+ string dataSize = item.Length > 0 ? string.Format("({0})", item.Length) : null;
+ if (item.DecimalDigits > 0&&item.Length>0 && dataType == "numeric")
+ {
+ dataSize = $"({item.Length},{item.DecimalDigits})";
+ }
+ string nullType = item.IsNullable ? this.CreateTableNull : CreateTableNotNull;
+ string primaryKey = null;
+ string addItem = string.Format(this.CreateTableColumn, this.SqlBuilder.GetTranslationColumnName(columnName.ToLower(isAutoToLowerCodeFirst)), dataType, dataSize, nullType, primaryKey, "");
+ if (item.IsIdentity)
+ {
+ string length = dataType.Substring(dataType.Length - 1);
+ string identityDataType = "serial" + length;
+ addItem = addItem.Replace(dataType, identityDataType);
+ }
+ columnArray.Add(addItem);
+ }
+ string tableString = string.Format(this.CreateTableSql, this.SqlBuilder.GetTranslationTableName(tableName.ToLower(isAutoToLowerCodeFirst)), string.Join(",\r\n", columnArray));
+ return tableString;
+ }
+ public override bool IsAnyConstraint(string constraintName)
+ {
+ throw new NotSupportedException("PgSql IsAnyConstraint NotSupportedException");
+ }
+ public override bool BackupDataBase(string databaseName, string fullFileName)
+ {
+ Check.ThrowNotSupportedException("PgSql BackupDataBase NotSupported");
+ return false;
+ }
+
+ public override List GetColumnInfosByTableName(string tableName, bool isCache = true)
+ {
+ var result= base.GetColumnInfosByTableName(tableName.TrimEnd('"').TrimStart('"').ToLower(), isCache);
+ if (result == null || result.Count() == 0)
+ {
+ result = base.GetColumnInfosByTableName(tableName, isCache);
+ }
+ try
+ {
+ string sql = $@"select
+ kcu.column_name as key_column
+ from information_schema.table_constraints tco
+ join information_schema.key_column_usage kcu
+ on kcu.constraint_name = tco.constraint_name
+ and kcu.constraint_schema = tco.constraint_schema
+ and kcu.constraint_name = tco.constraint_name
+ where tco.constraint_type = 'PRIMARY KEY'
+ and kcu.table_schema='{GetSchema()}' and
+ upper(kcu.table_name)=upper('{tableName.TrimEnd('"').TrimStart('"')}')";
+ List pkList = new List();
+ if (isCache)
+ {
+ pkList=GetListOrCache("GetColumnInfosByTableName_N_Pk"+tableName, sql);
+ }
+ else
+ {
+ pkList = this.Context.Ado.SqlQuery(sql);
+ }
+ if (pkList.Count >1)
+ {
+ foreach (var item in result)
+ {
+ if (pkList.Select(it=>it.ToUpper()).Contains(item.DbColumnName.ToUpper()))
+ {
+ item.IsPrimarykey = true;
+ }
+ }
+ }
+ }
+ catch
+ {
+
+ }
+ return result;
+ }
+ #endregion
+
+ #region Helper
+ private bool isAutoToLowerCodeFirst
+ {
+ get
+ {
+ if (this.Context.CurrentConnectionConfig.MoreSettings == null) return true;
+ else if (
+ this.Context.CurrentConnectionConfig.MoreSettings.PgSqlIsAutoToLower == false &&
+ this.Context.CurrentConnectionConfig.MoreSettings?.PgSqlIsAutoToLowerCodeFirst == false)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ private string GetSchema()
+ {
+ var schema = "public";
+ if (System.Text.RegularExpressions.Regex.IsMatch(this.Context.CurrentConnectionConfig.ConnectionString.ToLower(), "searchpath="))
+ {
+ var regValue = System.Text.RegularExpressions.Regex.Match(this.Context.CurrentConnectionConfig.ConnectionString.ToLower(), @"searchpath\=(\w+)").Groups[1].Value;
+ if (regValue.HasValue())
+ {
+ schema = regValue;
+ }
+ }
+ else if (System.Text.RegularExpressions.Regex.IsMatch(this.Context.CurrentConnectionConfig.ConnectionString.ToLower(), "search path="))
+ {
+ var regValue = System.Text.RegularExpressions.Regex.Match(this.Context.CurrentConnectionConfig.ConnectionString.ToLower(), @"search path\=(\w+)").Groups[1].Value;
+ if (regValue.HasValue())
+ {
+ schema = regValue;
+ }
+ }
+
+ return schema;
+ }
+
+ #endregion
+ }
+}
diff --git a/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/DuckDBProvider.cs b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/DuckDBProvider.cs
new file mode 100644
index 000000000..8c3fe4a33
--- /dev/null
+++ b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/DuckDBProvider.cs
@@ -0,0 +1,167 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.Common;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using DuckDB;
+using DuckDB.NET.Data;
+using DuckDB.NET.Native;
+
+namespace SqlSugar.DuckDB
+{
+ public partial class DuckDBProvider : AdoProvider
+ {
+ public DuckDBProvider()
+ {
+ if (StaticConfig.AppContext_ConvertInfinityDateTime == false)
+ {
+ AppContext.SetSwitch("DuckDB.EnableLegacyTimestampBehavior", true);
+ AppContext.SetSwitch("DuckDB.DisableDateTimeInfinityConversions", true);
+ }
+
+ }
+ public override IDbConnection Connection
+ {
+ get
+ {
+ if (base._DbConnection == null)
+ {
+ try
+ {
+ var DuckDBConnectionString = base.Context.CurrentConnectionConfig.ConnectionString;
+ base._DbConnection = new DuckDBConnection(DuckDBConnectionString);
+ }
+ catch (Exception)
+ {
+ throw;
+
+ }
+ }
+ return base._DbConnection;
+ }
+ set
+ {
+ base._DbConnection = value;
+ }
+ }
+
+ public override void BeginTran(string transactionName)
+ {
+ base.BeginTran();
+ }
+ ///
+ /// Only SqlServer
+ ///
+ ///
+ ///
+ public override void BeginTran(IsolationLevel iso, string transactionName)
+ {
+ base.BeginTran(iso);
+ }
+ public override IDataAdapter GetAdapter()
+ {
+ return new DuckDBDataAdapter();
+ }
+ public override DbCommand GetCommand(string sql, SugarParameter[] parameters)
+ {
+ DuckDBCommand sqlCommand = new DuckDBCommand(sql, (DuckDBConnection)this.Connection);
+ sqlCommand.CommandType = this.CommandType;
+ sqlCommand.CommandTimeout = this.CommandTimeOut;
+ if (this.Transaction != null)
+ {
+ sqlCommand.Transaction = (DuckDBTransaction)this.Transaction;
+ }
+ if (parameters.HasValue())
+ {
+ IDataParameter[] ipars = ToIDbDataParameter(parameters);
+ sqlCommand.Parameters.AddRange((DuckDBParameter[])ipars);
+ }
+ CheckConnection();
+ return sqlCommand;
+ }
+ public override void SetCommandToAdapter(IDataAdapter dataAdapter, DbCommand command)
+ {
+ ((DuckDBDataAdapter)dataAdapter).SelectCommand = (DuckDBCommand)command;
+ }
+ ///
+ /// if mysql return MySqlParameter[] pars
+ /// if sqlerver return SqlParameter[] pars ...
+ ///
+ ///
+ ///
+ public override IDataParameter[] ToIDbDataParameter(params SugarParameter[] parameters)
+ {
+ if (parameters == null || parameters.Length == 0) return null;
+ DuckDBParameter[] result = new DuckDBParameter[parameters.Length];
+ int index = 0;
+ var isVarchar = this.Context.IsVarchar();
+ foreach (var parameter in parameters)
+ {
+ if (parameter.Value == null) parameter.Value = DBNull.Value;
+ if (parameter.Value is System.Data.SqlTypes.SqlDateTime && parameter.DbType == System.Data.DbType.AnsiString)
+ {
+ parameter.DbType = System.Data.DbType.DateTime;
+ parameter.Value = DBNull.Value;
+ }
+ UNumber(parameter);
+ var sqlParameter = new DuckDBParameter();
+ sqlParameter.ParameterName = parameter.ParameterName;
+ sqlParameter.Size = parameter.Size;
+ sqlParameter.Value = parameter.Value;
+ sqlParameter.DbType = parameter.DbType;
+ sqlParameter.Direction = parameter.Direction;
+ //if (parameter.IsJson)
+ //{
+ // sqlParameter.DuckDBDbType = DuckDBType.Json;
+ //}
+ if (sqlParameter.Direction == 0)
+ {
+ sqlParameter.Direction = ParameterDirection.Input;
+ }
+ result[index] = sqlParameter;
+ if (sqlParameter.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput, ParameterDirection.ReturnValue))
+ {
+ if (this.OutputParameters == null) this.OutputParameters = new List();
+ this.OutputParameters.RemoveAll(it => it.ParameterName == sqlParameter.ParameterName);
+ this.OutputParameters.Add(sqlParameter);
+ }
+ if (isVarchar && sqlParameter.DbType == System.Data.DbType.String)
+ {
+ sqlParameter.DbType = System.Data.DbType.AnsiString;
+ }
+ else if (sqlParameter.Value is DateTime && sqlParameter.DbType == System.Data.DbType.AnsiString)
+ {
+ sqlParameter.DbType = System.Data.DbType.DateTime;
+ }
+ ++index;
+ //if (parameter.CustomDbType != null&& parameter.CustomDbType is DuckDBDbType)
+ //{
+ // sqlParameter.DbType = ((DuckDBType)parameter.CustomDbType);
+ //}
+ }
+ return result;
+ }
+
+ private static void UNumber(SugarParameter parameter)
+ {
+ if (parameter.DbType == System.Data.DbType.UInt16)
+ {
+ parameter.DbType = System.Data.DbType.Int16;
+ parameter.Value = Convert.ToInt16(parameter.Value);
+ }
+ else if (parameter.DbType == System.Data.DbType.UInt32)
+ {
+ parameter.DbType = System.Data.DbType.Int32;
+ parameter.Value = Convert.ToInt32(parameter.Value);
+ }
+ else if (parameter.DbType == System.Data.DbType.UInt64)
+ {
+ parameter.DbType = System.Data.DbType.Int64;
+ parameter.Value = Convert.ToInt64(parameter.Value);
+ }
+ }
+
+ }
+}
diff --git a/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/Insertable/DuckDBInserttable.cs b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/Insertable/DuckDBInserttable.cs
new file mode 100644
index 000000000..cf3f2835b
--- /dev/null
+++ b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/Insertable/DuckDBInserttable.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SqlSugar.DuckDB
+{
+ public class DuckDBInsertable : InsertableProvider where T : class, new()
+ {
+ public override int ExecuteReturnIdentity()
+ {
+ InsertBuilder.IsReturnIdentity = true;
+ PreToSql();
+ string identityColumn = GetIdentityColumn();
+ string sql = InsertBuilder.ToSqlString().Replace("$PrimaryKey", this.SqlBuilder.GetTranslationColumnName(identityColumn));
+ RestoreMapping();
+ var result = Ado.GetScalar(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()).ObjToInt();
+ After(sql, result);
+ return result;
+ }
+ public override async Task ExecuteReturnIdentityAsync()
+ {
+ InsertBuilder.IsReturnIdentity = true;
+ PreToSql();
+ string identityColumn = GetIdentityColumn();
+ string sql = InsertBuilder.ToSqlString().Replace("$PrimaryKey", this.SqlBuilder.GetTranslationColumnName(identityColumn));
+ RestoreMapping();
+ var obj = await Ado.GetScalarAsync(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray());
+ var result = obj.ObjToInt();
+ After(sql, result);
+ return result;
+ }
+ public override KeyValuePair> ToSql()
+ {
+ var result= base.ToSql();
+ var primaryKey = GetPrimaryKeys().FirstOrDefault();
+ if (primaryKey != null)
+ {
+ primaryKey = this.SqlBuilder.GetTranslationColumnName(primaryKey);
+ }
+ return new KeyValuePair>(result.Key.Replace("$PrimaryKey", primaryKey), result.Value);
+ }
+
+ public override long ExecuteReturnBigIdentity()
+ {
+ InsertBuilder.IsReturnIdentity = true;
+ PreToSql();
+ string sql = InsertBuilder.ToSqlString().Replace("$PrimaryKey", this.SqlBuilder.GetTranslationColumnName(GetIdentityKeys().FirstOrDefault()));
+ RestoreMapping();
+ var result = Convert.ToInt64(Ado.GetScalar(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()) ?? "0");
+ After(sql, result);
+ return result;
+ }
+ public override async Task ExecuteReturnBigIdentityAsync()
+ {
+ InsertBuilder.IsReturnIdentity = true;
+ PreToSql();
+ string sql = InsertBuilder.ToSqlString().Replace("$PrimaryKey", this.SqlBuilder.GetTranslationColumnName(GetIdentityKeys().FirstOrDefault()));
+ RestoreMapping();
+ var result = Convert.ToInt64(await Ado.GetScalarAsync(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()) ?? "0");
+ After(sql, result);
+ return result;
+ }
+
+ public override bool ExecuteCommandIdentityIntoEntity()
+ {
+ var result = InsertObjs.First();
+ var identityKeys = GetIdentityKeys();
+ if (identityKeys.Count == 0) { return this.ExecuteCommand() > 0; }
+ var idValue = ExecuteReturnBigIdentity();
+ Check.Exception(identityKeys.Count > 1, "ExecuteCommandIdentityIntoEntity does not support multiple identity keys");
+ var identityKey = identityKeys.First();
+ object setValue = 0;
+ if (idValue > int.MaxValue)
+ setValue = idValue;
+ else
+ setValue = Convert.ToInt32(idValue);
+ var propertyName = this.Context.EntityMaintenance.GetPropertyName(identityKey);
+ typeof(T).GetProperties().First(t => t.Name.ToUpper() == propertyName.ToUpper()).SetValue(result, setValue, null);
+ return idValue > 0;
+ }
+
+ private string GetIdentityColumn()
+ {
+ var identityColumn = GetIdentityKeys().FirstOrDefault();
+ if (identityColumn == null)
+ {
+ var columns = this.Context.DbMaintenance.GetColumnInfosByTableName(InsertBuilder.GetTableNameString);
+ identityColumn = columns.First(it => it.IsIdentity || it.IsPrimarykey).DbColumnName;
+ }
+ return identityColumn;
+ }
+
+ }
+}
diff --git a/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/Queryable/DuckDBQueryable.cs b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/Queryable/DuckDBQueryable.cs
new file mode 100644
index 000000000..927a1c08d
--- /dev/null
+++ b/Src/Asp.NetCore2/SqlSugar.DuckDBCore/DuckDB/Queryable/DuckDBQueryable.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SqlSugar.DuckDB
+{
+ public class DuckDBQueryable : QueryableProvider
+ {
+ public override ISugarQueryable With(string withString)
+ {
+ return this;
+ }
+
+ public override ISugarQueryable PartitionBy(string groupFileds)
+ {
+ this.GroupBy(groupFileds);
+ return this;
+ }
+ }
+ public class DuckDBQueryable : QueryableProvider
+ {
+ public new ISugarQueryable With(string withString)
+ {
+ return this;
+ }
+ }
+ public class DuckDBQueryable : QueryableProvider
+ {
+
+ }
+ public class DuckDBQueryable : QueryableProvider
+ {
+
+ }
+ public class DuckDBQueryable : QueryableProvider
+ {
+
+ }
+ public class DuckDBQueryable : QueryableProvider
+ {
+
+ }
+ public class DuckDBQueryable : QueryableProvider
+ {
+
+ }
+ public class DuckDBQueryable : QueryableProvider
+ {
+
+ }
+ public class DuckDBQueryable : QueryableProvider
+ {
+
+ }
+ public class DuckDBQueryable : QueryableProvider
+ {
+
+ }
+ public class DuckDBQueryable : QueryableProvider
+ {
+
+ }
+ public class DuckDBQueryable