本文聚焦 LiteOrm 的写入、更新、删除和批量操作。查询能力请统一参考 查询指南。
var user = new User
{
UserName = "admin",
Age = 30,
CreateTime = DateTime.Now,
DeptId = 1
};
bool success = await userService.InsertAsync(user);
await userService.BatchInsertAsync(users);
LiteOrm.Demo\Data\DbInitializer.cs 中使用批量插入来初始化部门、用户和销售记录,适合作为导入或初始化脚本参考:
var depts = new List<Department>
{
new() { Id = 1, Name = "集团总部" },
new() { Id = 2, Name = "研发中心", ParentId = 1 },
new() { Id = 3, Name = "市场部", ParentId = 1 }
};
await deptService.BatchInsertAsync(depts);
var users = new List<User>
{
new() { Id = 1, UserName = "Admin", Age = 35, CreateTime = DateTime.Now, DeptId = 1 },
new() { Id = 2, UserName = "研发负责人", Age = 32, CreateTime = DateTime.Now, DeptId = 2 }
};
await userService.BatchInsertAsync(users);
这个模式适合种子数据初始化、演示数据生成、批量导入前的数据准备。
bool success = await userService.UpdateOrInsertAsync(user);
Console.WriteLine(success); // true 表示执行成功
如果你需要区分本次到底是插入还是更新,可以直接使用 DAO 层的 UpdateOrInsertResult。
await userService.BatchUpdateOrInsertAsync(users);
下面的例子提炼自 LiteOrm.Tests\ServiceTests.cs:同一批数据中既有“已存在需要更新”的实体,也有“需要新增”的实体。
var users = new List<TestUser>
{
new TestUser { Name = "Upsert A", Age = 10, CreateTime = DateTime.Now },
new TestUser { Name = "Upsert B", Age = 20, CreateTime = DateTime.Now }
};
await service.BatchInsertAsync(users);
var existingUser = users[0];
existingUser.Age = 15; // 更新现有记录
var newUser = new TestUser
{
Name = "Upsert C",
Age = 30,
CreateTime = DateTime.Now
};
await service.BatchUpdateOrInsertAsync(new[] { existingUser, newUser });
执行后,Upsert A 会被更新,Upsert C 会被插入。
var user = await userService.SearchOneAsync(u => u.Id == 1);
user.UserName = "admin_v2";
await userService.UpdateAsync(user);
foreach (var user in users)
{
user.Age += 1;
}
await userService.BatchUpdateAsync(users);
LiteOrm.Demo\Data\DbInitializer.cs 中先查询出部门,再集中修改负责人,最后一次性提交:
var updateDepts = new List<Department>();
async Task MarkManager(int deptId, int managerId)
{
var dept = await deptService.GetObjectAsync(deptId);
if (dept != null)
{
dept.ManagerId = managerId;
updateDepts.Add(dept);
}
}
await MarkManager(1, 1);
await MarkManager(2, 2);
await MarkManager(4, 6);
await deptService.BatchUpdateAsync(updateDepts);
适合“先读出实体,修改多个对象,再批量提交”的后台管理场景。
timestamp 做乐观并发更新如果你希望更新时额外校验“读取时版本”和“提交时版本”是否一致,可以给实体声明一个 timestamp 列,然后使用 ObjectDAO<T> 的 Update(entity, timestamp) / UpdateAsync(entity, timestamp) 重载。
[Table("Users")]
public class User : ObjectBase
{
[Column("Id", IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
[Column("UserName")]
public string? UserName { get; set; }
[Column("Version", IsTimestamp = true)]
public int Version { get; set; }
}
var dao = serviceProvider.GetRequiredService<ObjectDAO<User>>();
var viewDao = serviceProvider.GetRequiredService<ObjectViewDAO<User>>();
var user = await viewDao.GetObject(1).FirstOrDefaultAsync();
int originalVersion = user.Version;
user.UserName = "admin_v2";
user.Version = originalVersion + 1; // 实体上的值会写回数据库
bool updated = await dao.UpdateAsync(user, originalVersion);
if (!updated)
{
Console.WriteLine("发生并发冲突,记录已被其他人修改。");
}
这一重载的行为要点:
Version 是将要写入数据库的新值。timestamp 参数是查询时拿到的旧值,会被放进 WHERE 条件里做并发校验。false 时,通常表示主键存在,但 timestamp 已不匹配。IEntityService<T> / IEntityServiceAsync<T> 的 Update 重载不带 timestamp 参数;需要乐观并发时,请直接使用 ObjectDAO<T>,或在自定义 Service 中封装 DAO。BatchUpdate / BatchUpdateAsync 不会自动附带 timestamp 并发校验。timestamp 更新示例可参考:
LiteOrm.Tests\ObjectDAOTests.csLiteOrm.Tests\Models\TestTimestampUser.csusing static LiteOrm.Common.Expr;
await objectDao.UpdateAsync(
Update<User>()
.Where(Prop("Age") < 18)
.Set(
("Age", Value(18)),
("CreateTime", Value(DateTime.Now))
)
);
LiteOrm.Demo\Demos\UpdateExprDemo.cs 演示了 UpdateExpr 的几种典型玩法:
using static LiteOrm.Common.Expr;
var update = new UpdateExpr(new TableExpr(typeof(User)), Prop("UserName") == "UpdateDemo_Bob")
.Set(("Age", Const(35)));
int affected = await userService.UpdateAsync(update);
也可以直接在 SET 子句里写算术表达式或函数表达式:
using static LiteOrm.Common.Expr;
var agePlusFive = new UpdateExpr(new TableExpr(typeof(User)), Prop("UserName") == "UpdateDemo_Carol")
.Set(("Age", Prop("Age") + Const(5)));
var rename = new UpdateExpr(new TableExpr(typeof(User)), Prop("UserName") == "UpdateDemo_Bob")
.Set(("UserName", Func("CONCAT", Prop("UserName"), Const("_v2"))));
var user = await userService.SearchOneAsync(u => u.Id == 1);
await userService.DeleteAsync(user);
await userService.DeleteAsync(1);
await userService.BatchDeleteAsync(users);
await userService.BatchDeleteIDAsync(new[] { 1, 2, 3 });
LiteOrm.Tests\ServiceTests.cs 中有一组很适合复制的闭环验证:
using static LiteOrm.Common.Expr;
var users = new List<TestUser>
{
new TestUser { Name = "Batch 1", Age = 10, CreateTime = DateTime.Now },
new TestUser { Name = "Batch 2", Age = 20, CreateTime = DateTime.Now }
};
await service.BatchInsertAsync(users);
var inserted = await viewService.SearchAsync(Lambda<TestUser>(u => u.Name!.StartsWith("Batch")));
foreach (var user in inserted)
user.Age += 5;
await service.BatchUpdateAsync(inserted);
await service.BatchDeleteAsync(inserted);
这个例子很适合验证批量接口是否能覆盖“插入 → 更新 → 删除”的整条路径。
using static LiteOrm.Common.Expr;
await userService.DeleteAsync(u => u.CreateTime < DateTime.Today.AddYears(-1));
await objectDao.Delete(Prop("Age") < 18 & Prop("UserName").StartsWith("Temp"));
以下例子提炼自分表测试,但删除条件本身同样适用于普通表:
int deleted = await service.DeleteAsync(
l => l.Amount > 400 && l.Event == "DeleteEvent",
tableArgs: new[] { "202401" }
);
如果不是分表场景,去掉 tableArgs 即可。
| 方法类型 | 常见返回值 | 含义 |
|---|---|---|
Insert/Update/Delete |
bool |
是否成功执行。 |
| 条件更新/删除 | int |
受影响行数。 |
Service 层 UpdateOrInsert |
bool |
是否成功执行。 |
DAO 层 UpdateOrInsert |
UpdateOrInsertResult |
告知本次是插入还是更新。 |
IEntityService<T> / IEntityServiceAsync<T>Insert / InsertAsyncUpdate / UpdateAsyncDelete / DeleteAsyncBatchInsert / BatchInsertAsyncBatchUpdate / BatchUpdateAsyncBatchDelete / BatchDeleteAsyncUpdateOrInsert / UpdateOrInsertAsync如果你还需要按条件搜索、分页、Exists、Count 等能力,请转到 查询指南。
除了 BatchInsertAsync、BatchUpdateAsync、BatchDeleteAsync 这类同构操作,LiteOrm 还支持把不同操作放进同一批处理中。
var newUser = new TestUser { Name = "Mixed 1", Age = 10, CreateTime = DateTime.Now };
var ops = new List<EntityOperation<TestUser>>
{
new EntityOperation<TestUser> { Entity = newUser, Operation = OpDef.Insert },
new EntityOperation<TestUser> { Entity = existingUser, Operation = OpDef.Delete }
};
await service.BatchAsync(ops);
这个例子来自 LiteOrm.Tests\ServiceTests.cs,适合需要“新增一批数据,同时删除旧数据”的同步迁移场景。
Expr.Update<T>() 和 DAO。