使用SqlSugar進行動態創建和操作表--CRUD
在SqlSugar中動態創建表和進行CRUD操作,可以通過以下步驟實現。這里使用動態對象(ExpandoObject)或字典表示數據,并使用動態表名進行操作:
1. 安裝SqlSugar
Install-Package SqlSugar
2. 動態創建表與CRUD示例
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
public class DynamicTableService
{
private readonly SqlSugarClient _db;
public DynamicTableService(string connectionString)
{
_db = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = connectionString,
DbType = DbType.SqlServer, // 根據數據庫修改(支持MySQL、SQLite等)
IsAutoCloseConnection = true,
});
// 初始化ORM配置
_db.Aop.OnLogExecuting = (sql, pars) => Console.WriteLine(sql);
}
// 動態創建表(若不存在)
public void CreateTableIfNotExists(string tableName, List<TableColumn> columns)
{
// 生成動態類型(通過反射Emit創建)
var entityType = DynamicTypeBuilder.CreateType(columns);
// 使用CodeFirst同步表結構
_db.CodeFirst.InitTables(entityType); // 自動根據類名建表
// 如果表名需要自定義(與類名不同),需添加特性 [SugarTable("TableName")]
}
// 插入數據
public int Insert(string tableName, ExpandoObject entity)
{
return _db.InsertableByObject(entity).AS(tableName).ExecuteCommand();
}
// 批量插入
public int InsertRange(string tableName, List<ExpandoObject> entities)
{
return _db.InsertableByObject(entities).AS(tableName).ExecuteCommand();
}
// 更新數據
public int Update(string tableName, ExpandoObject entity, string primaryKey = "Id")
{
dynamic expando = entity;
var id = ((IDictionary<string, object>)entity)[primaryKey];
return _db.UpdateableByObject(entity)
.AS(tableName)
.WhereColumns(primaryKey, id.ToString())
.ExecuteCommand();
}
// 刪除數據(根據主鍵)
public int Delete(string tableName, object primaryKeyValue, string primaryKey = "Id")
{
return _db.Deleteable<object>()
.AS(tableName)
.Where($"{primaryKey} = @id", new { id = primaryKeyValue })
.ExecuteCommand();
}
// 查詢所有數據
public List<ExpandoObject> GetAll(string tableName)
{
return _db.Queryable<ExpandoObject>().AS(tableName).ToList();
}
// 條件查詢
public List<ExpandoObject> Where(string tableName, string whereSql, object parameters = null)
{
return _db.Queryable<ExpandoObject>().AS(tableName).Where(whereSql, parameters).ToList();
}
}
// 列定義結構
public class TableColumn
{
public string Name { get; set; }
public Type Type { get; set; } // 如:typeof(int), typeof(string)
public bool IsPrimaryKey { get; set; } = false;
public bool IsIdentity { get; set; } = false;
}
// 動態類型生成工具(通過反射Emit)
public static class DynamicTypeBuilder
{
public static Type CreateType(List<TableColumn> columns)
{
var typeBuilder = DynamicModule.CreateTypeBuilder();
foreach (var col in columns)
{
DynamicModule.CreateProperty(typeBuilder, col.Name, col.Type);
// 添加主鍵和自增特性
if (col.IsPrimaryKey)
{
typeBuilder.AddSugarPrimaryKey(col.Name, col.IsIdentity);
}
}
return typeBuilder.CreateType();
}
}
// 動態構建模塊
public static class DynamicModule
{
private static readonly System.Reflection.Emit.ModuleBuilder _moduleBuilder;
static DynamicModule()
{
var assemblyName = new System.Reflection.AssemblyName("DynamicTypes");
var assemblyBuilder = System.Reflection.Emit.AssemblyBuilder.DefineDynamicAssembly(
assemblyName, System.Reflection.Emit.AssemblyBuilderAccess.Run);
_moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");
}
public static System.Reflection.Emit.TypeBuilder CreateTypeBuilder()
{
string typeName = "DynamicType_" + Guid.NewGuid().ToString("N");
return _moduleBuilder.DefineType(typeName, System.Reflection.TypeAttributes.Public);
}
public static void CreateProperty(System.Reflection.Emit.TypeBuilder typeBuilder, string name, Type type)
{
var fieldBuilder = typeBuilder.DefineField("_" + name, type, System.Reflection.FieldAttributes.Private);
var propertyBuilder = typeBuilder.DefineProperty(
name,
System.Reflection.PropertyAttributes.None,
type,
Type.EmptyTypes);
var getMethod = typeBuilder.DefineMethod(
"get_" + name,
System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.SpecialName,
type,
Type.EmptyTypes);
var getIL = getMethod.GetILGenerator();
getIL.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
getIL.Emit(System.Reflection.Emit.OpCodes.Ldfld, fieldBuilder);
getIL.Emit(System.Reflection.Emit.OpCodes.Ret);
var setMethod = typeBuilder.DefineMethod(
"set_" + name,
System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.SpecialName,
null,
new[] { type });
var setIL = setMethod.GetILGenerator();
setIL.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
setIL.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
setIL.Emit(System.Reflection.Emit.OpCodes.Stfld, fieldBuilder);
setIL.Emit(System.Reflection.Emit.OpCodes.Ret);
propertyBuilder.SetGetMethod(getMethod);
propertyBuilder.SetSetMethod(setMethod);
}
public static void AddSugarPrimaryKey(
this System.Reflection.Emit.TypeBuilder typeBuilder,
string propertyName,
bool isIdentity)
{
// 為屬性添加 [SugarColumn(IsPrimaryKey=true, IsIdentity=true)] 特性
var attrType = typeof(SugarColumn);
var ctor = attrType.GetConstructor(new Type[] { });
var builder = new System.Reflection.Emit.CustomAttributeBuilder(
ctor, new object[] { },
new[] { typeof(SugarColumn).GetProperty("IsPrimaryKey") },
new object[] { true },
new[] { typeof(SugarColumn).GetProperty("IsIdentity") },
new object[] { isIdentity }
);
typeBuilder.DefineProperty(
propertyName,
System.Reflection.PropertyAttributes.None,
null, null)
.SetCustomAttribute(builder);
}
}
使用示例
var service = new DynamicTableService("YourConnectionString");
// 定義動態表結構
var columns = new List<TableColumn>
{
new TableColumn { Name = "Id", Type = typeof(int), IsPrimaryKey = true, IsIdentity = true },
new TableColumn { Name = "Name", Type = typeof(string) },
new TableColumn { Name = "Age", Type = typeof(int) }
};
// 創建表(自動根據類名同步表結構)
service.CreateTableIfNotExists("DynamicPerson", columns);
// 插入數據
dynamic data = new ExpandoObject();
data.Name = "Alice";
data.Age = 30;
service.Insert("DynamicPerson", data);
// 查詢
var allData = service.GetAll("DynamicPerson");
foreach (dynamic item in allData)
{
Console.WriteLine($"Id: {item.Id}, Name: {item.Name}");
}
// 條件查詢
var adults = service.Where("DynamicPerson", "Age > @age", new { age = 18 });
關鍵說明
-
動態表創建
- 使用
DynamicTypeBuilder運行時生成實體類。 - 通過
db.CodeFirst.InitTables(type)同步表結構。
- 使用
-
動態CRUD
- 插入:
InsertableByObject+AS(tableName) - 查詢:
Queryable<ExpandoObject>()+AS(tableName) - 支持動態條件拼接(
Where中使用參數化SQL避免注入)。
- 插入:
-
注意事項
- 不同數據庫(如MySQL/SQLite)需修改
DbType。 - 主鍵自增需在列定義中設置
IsIdentity=true。 - 實際生產環境中建議添加異常處理和事務。
- 不同數據庫(如MySQL/SQLite)需修改
-
高級場景
- 動態修改表結構:使用
db.DbMaintenance操作DDL語句。 - 分表分庫:結合
SplitTable功能實現(需額外配置)。
- 動態修改表結構:使用
通過這種方式,你可以在SqlSugar中靈活操作動態生成的表結構并執行CRUD操作。

浙公網安備 33010602011771號