ORMX的CRUD操作 - 开发日志,CRUD操作, 插入数据, 查询数据, 更新数据, 删除数据, MongoDB操作 - 学习ORMX的CRUD操作,包括数据的插入、查询、更新和删除,以及MongoDB特定的操作。

您当前正在浏览的是本站SEO版网页

请点击确认

马上提升浏览体验

ORMX的CRUD操作

编程 数据库 阅读:0
2/8/2026 9:12:23 PM

学习ORMX的CRUD操作,包括数据的插入、查询、更新和删除,以及MongoDB特定的操作。 关键字:CRUD操作, 插入数据, 查询数据, 更新数据, 删除数据, MongoDB操作

第六章:CRUD操作

6.1 Create(插入数据)

6.1.1 单个插入

使用 Insert 方法插入单个实体:

using var userTable = tableManager.Table<User>();

var user = new User
{
    Name = "张三",
    Email = "zhangsan@example.com",
    Age = 25
};

var insertedUser = userTable.Insert(user);
Console.WriteLine(<div class="latex">$"插入成功,ID: {insertedUser.Id}");

说明:

  • Insert 方法会自动生成 INSERT 语句
  • 如果主键是自增的,插入后会自动填充 ID 值
  • 返回的实体包含数据库生成的值(如自增 ID)

6.1.2 批量插入

使用 InsertAll 方法批量插入多个实体:

using var userTable = tableManager.Table<User>();

var users = new List<User>
{
    new User { Name = "张三", Email = "zhangsan@example.com", Age = 25 },
    new User { Name = "李四", Email = "lisi@example.com", Age = 30 },
    new User { Name = "王五", Email = "wangwu@example.com", Age = 28 }
};

var insertedUsers = userTable.InsertAll(users);
Console.WriteLine($</div>"批量插入了 {insertedUsers.Count} 个用户");

说明:

  • InsertAll 方法会生成批量 INSERT 语句
  • 性能优于逐个插入,适合大量数据
  • 返回的实体列表包含数据库生成的值

6.1.3 插入注意事项

  1. 主键处理

    • 如果主键是自增的,不需要设置 ID 值
    • 如果主键不是自增的,需要手动设置 ID 值
  2. 可空字段

    • 可空字段可以不设置值
    • 不可空字段必须设置值
  3. 默认值

    • 如果字段有默认值,可以不设置该字段的值
    • 数据库会使用默认值
  4. 数据类型

    • 确保数据类型与数据库列类型匹配
    • ORMX 会自动进行类型转换

6.1.4 MongoDB 特定的插入操作

MongoDB 插入特点

  • MongoDB 使用 _id 字段作为主键,ORMX 会自动映射到实体的 Id 属性
  • 对于整数类型的 Id,ORMX 会自动转换为 MongoDB 的 ObjectId 或保持为整数
  • 插入操作会返回包含完整 Id 值的实体

MongoDB 插入示例

using JCode.ORMX.DbProvider.MongoDB;

// 创建 MongoDB 提供程序
using var provider = new MongoDBProvider("mongodb://localhost:27017", "mydb");
var tableManager = provider.GetTableManager();

// 获取表对象
var userTable = tableManager.Table<User>();

// 单个插入
var user = new User
{
    Name = "张三",
    Email = "zhangsan@example.com",
    Age = 25,
    CreatedAt = DateTime.Now,
    IsActive = true
};

var insertedUser = userTable.Insert(user);
Console.WriteLine(<div class="latex">$"插入成功,ID: {insertedUser.Id}");

// 批量插入
var users = new List<User>
{
    new User { Name = "李四", Email = "lisi@example.com", Age = 30 },
    new User { Name = "王五", Email = "wangwu@example.com", Age = 28 }
};

var insertedUsers = userTable.InsertAll(users);
Console.WriteLine($</div>"批量插入了 {insertedUsers.Count} 个用户");
foreach (var u in insertedUsers)
{
    Console.WriteLine(<div class="latex">$"  - {u.Name}, ID: {u.Id}");
}

MongoDB 插入注意事项

  1. _id 字段映射:实体的 Id 属性会自动映射到 MongoDB 的 _id 字段
  2. 类型转换:ORMX 会根据 Id 属性的类型自动选择合适的 MongoDB 类型
  3. 批量操作:批量插入在 MongoDB 中性能优于单个插入
  4. 会话支持:在事务中,插入操作会使用 MongoDB 会话

关于实体映射的详细说明,请查阅实体映射

6.2 Read(查询数据)

6.2.1 根据 ID 查找

使用 Where 方法结合 FirstOrDefault 根据主键查找单个实体:

using var userTable = tableManager.Table<User>();

var user = userTable.Where(u => u.Id == 1).FirstOrDefault();
if (user != null)
{
    Console.WriteLine($</div>"找到用户: {user.Name}, 邮箱: {user.Email}");
}
else
{
    Console.WriteLine("用户不存在");
}

说明:

  • Where 方法用于设置查询条件
  • FirstOrDefault 方法返回第一个匹配的实体,如果找不到返回 null
  • 适用于主键查询场景

6.2.2 查找所有数据

使用 GetList 方法查找所有实体:

using var userTable = tableManager.Table<User>();

var users = userTable.GetList();
Console.WriteLine(<div class="latex">$"总共有 {users.Count} 个用户");

foreach (var user in users)
{
    Console.WriteLine($</div>"ID: {user.Id}, 姓名: {user.Name}, 邮箱: {user.Email}");
}

说明:

  • GetList 方法返回所有实体
  • 返回类型为 List<T>
  • 适用于数据量不大的场景

6.2.3 类型映射

ORMX 会自动将数据库类型映射到 C# 类型:

// 数据库类型 -> C# 类型
INTEGER -> int
TEXT -> string
REAL -> double
BLOB -> byte[]
DATETIME -> DateTime
BOOLEAN -> bool

示例:

public class User
{
    [Column(IsPrimaryKey = true, IsAutoIncrement = true)]
    public int Id { get; set; }
    
    public string Name { get; set; }
    
    public string Email { get; set; }
    
    public int Age { get; set; }
    
    public DateTime CreatedAt { get; set; }
    
    public bool IsActive { get; set; }
}

// 查询时自动映射
var user = userTable.Where(u => u.Id == 1).FirstOrDefault();
Console.WriteLine(user.CreatedAt); // DateTime 类型
Console.WriteLine(user.IsActive);  // bool 类型

6.2.4 MongoDB 特定的查询操作

MongoDB 查询特点

  • MongoDB 使用文档查询语法,ORMX 会自动将 LINQ 查询转换为 MongoDB 查询
  • 支持基本的比较操作符(==, !=, >, <, >=, ⇐)
  • 支持逻辑操作符(&&, ||, !)
  • 支持字符串操作(Contains, StartsWith, EndsWith)

MongoDB 查询示例

using JCode.ORMX.DbProvider.MongoDB;

// 创建 MongoDB 提供程序
using var provider = new MongoDBProvider("mongodb://localhost:27017", "mydb");
var tableManager = provider.GetTableManager();

// 获取表对象
var userTable = tableManager.Table<User>();

// 根据 ID 查询
var userById = userTable.Where(u => u.Id == 1).FirstOrDefault();
if (userById != null)
{
    Console.WriteLine(<div class="latex">$"找到用户: {userById.Name}");
}

// 条件查询
var activeUsers = userTable.Where(u => u.IsActive == true && u.Age > 18).GetList();
Console.WriteLine($</div>"找到 {activeUsers.Count} 个活跃用户");

// 字符串查询
var usersWithEmail = userTable.Where(u => u.Email.Contains("example.com")).GetList();
Console.WriteLine(<div class="latex">$"找到 {usersWithEmail.Count} 个使用 example.com 邮箱的用户");

// 排序查询
var sortedUsers = userTable.Where(u => u.Age > 20).OrderByDescending(u => u.Age).GetList();
Console.WriteLine("按年龄降序排列的用户:");
foreach (var u in sortedUsers)
{
    Console.WriteLine($</div>"  - {u.Name}, 年龄: {u.Age}");
}

// 分页查询
var pagedUsers = userTable.Where(u => u.IsActive == true)
    .OrderBy(u => u.Name)
    .Offset(0)
    .Limit(10)
    .GetList();
Console.WriteLine("第 1 页用户(10 个):");
foreach (var u in pagedUsers)
{
    Console.WriteLine(<div class="latex">$"  - {u.Name}");
}

MongoDB 查询注意事项

  1. 字段映射:ORMX 会自动处理实体属性到 MongoDB 字段的映射
  2. 类型转换:自动处理 C# 类型到 MongoDB BSON 类型的转换
  3. 查询优化:对于频繁查询的字段,建议在 MongoDB 中创建索引
  4. 复杂查询:复杂的 LINQ 查询可能无法完全转换为 MongoDB 查询语法

关于查询构建的详细说明,请参考查询构建

6.3 Update(更新数据)

6.3.1 单个更新

使用 Update 方法更新单个实体:

using var userTable = tableManager.Table<User>();

// 先查询
var user = userTable.Where(u => u.Id == 1).FirstOrDefault();
if (user != null)
{
    // 修改属性
    user.Age = 26;
    user.Email = "newemail@example.com";
    
    // 更新
    userTable.Update(user);
    Console.WriteLine("更新成功");
}

说明:

  • Update 方法会根据主键生成 UPDATE 语句
  • 只更新修改过的字段
  • 返回受影响的行数

6.3.2 批量更新

使用 UpdateAll 方法批量更新多个实体:

using var userTable = tableManager.Table<User>();

// 查询所有用户
var users = userTable.GetList();

// 修改所有用户的年龄
foreach (var user in users)
{
    user.Age += 1;
}

// 批量更新
userTable.UpdateAll(users);
Console.WriteLine($</div>"批量更新了 {users.Count} 个用户");

说明:

  • UpdateAll 方法会生成批量 UPDATE 语句
  • 性能优于逐个更新
  • 适合批量修改数据的场景

6.3.3 类型安全的字段更新

使用 Update 方法的重载,可以只更新指定字段:

using var userTable = tableManager.Table<User>();

// 只更新 Age 字段
userTable.Update(1, new { Age = 30 });

// 更新多个字段
userTable.Update(1, new { Age = 30, Email = "updated@example.com" });

说明:

  • 使用匿名对象指定要更新的字段
  • 只更新指定的字段,其他字段保持不变
  • 类型安全,编译时检查

6.3.4 更新注意事项

  1. 主键不能修改

    • 更新时不能修改主键值
    • 如果需要修改主键,需要先删除再插入
  2. 并发控制

    • ORMX 不提供自动的并发控制
    • 需要手动实现乐观锁或悲观锁
  3. 部分更新

    • 如果只需要更新部分字段,使用匿名对象更新
    • 避免加载整个实体再更新

6.3.5 MongoDB 特定的更新操作

MongoDB 更新特点

  • MongoDB 使用 updateOneupdateMany 操作
  • ORMX 会自动根据实体的 Id 字段定位文档
  • 支持部分字段更新,只更新修改过的字段

MongoDB 更新示例

using JCode.ORMX.DbProvider.MongoDB;

// 创建 MongoDB 提供程序
using var provider = new MongoDBProvider("mongodb://localhost:27017", "mydb");
var tableManager = provider.GetTableManager();

// 获取表对象
var userTable = tableManager.Table<User>();

// 单个更新
var user = userTable.Where(u => u.Id == 1).FirstOrDefault();
if (user != null)
{
    // 修改属性
    user.Age = 26;
    user.Email = "newemail@example.com";
    user.IsActive = true;
    
    // 更新
    var affectedRows = userTable.Update(user);
    Console.WriteLine(<div class="latex">$"更新成功,影响行数:{affectedRows}");
}

// 批量更新(使用条件)
var updateCount = userTable.Where(u => u.Age < 18).Update(u => new User { IsActive = false });
Console.WriteLine($</div>"批量更新了 {updateCount} 个用户");

// 部分字段更新
var partialUpdateCount = userTable.Update(1, new { Age = 27, Email = "updated@example.com" });
Console.WriteLine(<div class="latex">$"部分更新成功,影响行数:{partialUpdateCount}");

MongoDB 更新注意事项

  1. _id 字段:更新操作会使用 _id 字段定位文档,确保实体包含正确的 Id
  2. 字段映射:ORMX 会自动处理实体属性到 MongoDB 字段的映射
  3. 类型转换:自动处理 C# 类型到 MongoDB BSON 类型的转换
  4. 性能考虑:对于大量数据的更新,建议使用批量更新操作

6.4 Delete(删除数据)

6.4.1 单个删除

使用 Delete 方法删除单个实体:

using var userTable = tableManager.Table<User>();

// 先查询要删除的实体
var user = userTable.Where(u => u.Id == 1).FirstOrDefault();
if (user != null)
{
    var affectedRows = userTable.Delete(user);
    Console.WriteLine($</div>"删除成功,影响行数:{affectedRows}");
}
else
{
    Console.WriteLine("删除失败,用户不存在");
}

说明:

  • Delete 方法接受实体对象作为参数
  • 返回影响的行数
  • 如果找不到记录,返回 0

6.4.2 批量删除

使用 DeleteAll 方法批量删除多个实体:

using var userTable = tableManager.Table<User>();

// 查询要删除的用户
var users = userTable.Where(u => u.Age < 18).GetList();

// 批量删除
var deletedCount = userTable.DeleteAll(users);
Console.WriteLine(<div class="latex">$"批量删除了 {deletedCount} 个用户");

说明:

  • DeleteAll 方法会生成批量 DELETE 语句
  • 性能优于逐个删除
  • 适合批量删除数据的场景

6.4.3 根据条件删除

使用 Delete 方法配合 Where 条件删除:

using var userTable = tableManager.Table<User>();

// 删除年龄小于 18 的用户
var deletedCount = userTable.Where(u => u.Age < 18).Delete();
Console.WriteLine($</div>"删除了 {deletedCount} 个用户");

说明:

  • 使用 Where 方法指定删除条件
  • 类型安全,编译时检查
  • 返回删除的记录数

6.4.4 清空表

使用 Truncate 方法清空表:

using var userTable = tableManager.Table<User>();

var success = userTable.Truncate();
if (success)
{
    Console.WriteLine("表已清空");
}

说明:

  • Truncate 方法会删除表中的所有数据
  • 比逐个删除更高效
  • 会重置自增 ID

6.4.5 删除表

使用 Drop 方法删除表:

using var userTable = tableManager.Table<User>();

var success = userTable.Drop();
if (success)
{
    Console.WriteLine("表已删除");
}

说明:

  • Drop 方法会删除整个表
  • 包括表结构和数据
  • 慎用,不可恢复

6.4.6 删除注意事项

  1. 级联删除

    • ORMX 不提供自动的级联删除
    • 需要在数据库层面设置外键约束
  2. 软删除

    • 如果需要软删除,可以添加 IsDeleted 字段
    • 使用更新操作代替删除操作
  3. 事务保护

    • 删除操作应该在事务中执行
    • 确保数据一致性

6.4.7 MongoDB 特定的删除操作

MongoDB 删除特点

  • MongoDB 使用 deleteOnedeleteMany 操作
  • ORMX 会自动根据实体的 Id 字段定位文档
  • 支持条件删除多个文档

MongoDB 删除示例

using JCode.ORMX.DbProvider.MongoDB;

// 创建 MongoDB 提供程序
using var provider = new MongoDBProvider("mongodb://localhost:27017", "mydb");
var tableManager = provider.GetTableManager();

// 获取表对象
var userTable = tableManager.Table<User>();

// 单个删除
var user = userTable.Where(u => u.Id == 1).FirstOrDefault();
if (user != null)
{
    var affectedRows = userTable.Delete(user);
    Console.WriteLine(<div class="latex">$"删除成功,影响行数:{affectedRows}");
}

// 根据 ID 删除
var deletedById = userTable.DeleteById(2);
Console.WriteLine($</div>"根据 ID 删除,影响行数:{deletedById}");

// 批量删除(使用条件)
var deleteCount = userTable.Where(u => u.Age < 18).Delete();
Console.WriteLine(<div class="latex">$"批量删除了 {deleteCount} 个用户");

MongoDB 删除注意事项

  1. _id 字段:删除操作会使用 _id 字段定位文档
  2. 条件删除:批量删除操作会转换为 MongoDB 的 deleteMany 操作
  3. 性能考虑:对于大量数据的删除,建议分批删除或使用索引
  4. 事务支持:在事务中,删除操作会使用 MongoDB 会话

关于事务处理的详细用法,请查阅事务处理

6.5 完整示例

6.5.1 用户管理系统

下面是一个完整的用户管理系统示例,演示所有 CRUD 操作:

using System;
using System.Collections.Generic;
using JCode.ORMX.Attributes;
using JCode.ORMX.DbProvider;
using JCode.ORMX.Core;
using Microsoft.Data.Sqlite;

// 定义实体类
[Table(Name = "Users")]
public class User
{
    [Column(IsPrimaryKey = true, IsAutoIncrement = true)]
    public int Id { get; set; }
    
    public string Name { get; set; }
    
    public string Email { get; set; }
    
    public int Age { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        // 创建数据库提供程序(推荐方式)
        using var provider = new SqliteDatabaseProvider("Data Source=:memory:");
        var tableManager = provider.GetTableManager();

        var userTable = tableManager.Table<User>();

        // 1. 创建用户
        Console.WriteLine("=== 创建用户 ===");
        var users = new List<User>
        {
            new User { Name = "张三", Email = "zhangsan@example.com", Age = 25 },
            new User { Name = "李四", Email = "lisi@example.com", Age = 30 },
            new User { Name = "王五", Email = "wangwu@example.com", Age = 28 }
        };
        userTable.InsertAll(users);
        Console.WriteLine($</div>"创建了 {users.Count} 个用户");
        
        // 2. 查询所有用户
        Console.WriteLine("\n=== 查询所有用户 ===");
        var allUsers = userTable.GetList();
        foreach (var user in allUsers)
        {
            Console.WriteLine(<div class="latex">$"ID: {user.Id}, 姓名: {user.Name}, 邮箱: {user.Email}, 年龄: {user.Age}");
        }
        
        // 3. 根据 ID 查找用户
        Console.WriteLine("\n=== 根据 ID 查找用户 ===");
        var user = userTable.Where(u => u.Id == 1).FirstOrDefault();
        if (user != null)
        {
            Console.WriteLine($</div>"找到用户: {user.Name}, 邮箱: {user.Email}, 年龄: {user.Age}");
        }
        
        // 4. 更新用户
        Console.WriteLine("\n=== 更新用户 ===");
        user.Age = 26;
        userTable.Update(user);
        var updatedUser = userTable.Where(u => u.Id == 1).FirstOrDefault();
        Console.WriteLine(<div class="latex">$"用户年龄已更新为: {updatedUser.Age}");
        
        // 5. 删除用户
        Console.WriteLine("\n=== 删除用户 ===");
        var success = userTable.Delete(3);
        if (success)
        {
            Console.WriteLine("用户删除成功");
        }
        
        // 6. 查询剩余用户
        Console.WriteLine("\n=== 查询剩余用户 ===");
        var remainingUsers = userTable.GetList();
        Console.WriteLine($</div>"剩余 {remainingUsers.Count} 个用户");
        foreach (var remainingUser in remainingUsers)
        {
            Console.WriteLine(<div class="latex">$"ID: {remainingUser.Id}, 姓名: {remainingUser.Name}");
        }
    }
}

运行结果:

=== 创建用户 ===
创建了 3 个用户

=== 查询所有用户 ===
ID: 1, 姓名: 张三, 邮箱: zhangsan@example.com, 年龄: 25
ID: 2, 姓名: 李四, 邮箱: lisi@example.com, 年龄: 30
ID: 3, 姓名: 王五, 邮箱: wangwu@example.com, 年龄: 28

=== 根据 ID 查找用户 ===
找到用户: 张三, 邮箱: zhangsan@example.com, 年龄: 25

=== 更新用户 ===
用户年龄已更新为: 26

=== 删除用户 ===
用户删除成功

=== 查询剩余用户 ===
剩余 2 个用户
ID: 1, 姓名: 张三
ID: 2, 姓名: 李四

6.6 最佳实践

6.6.1 使用事务

对于涉及多个操作的场景,应该使用事务:

using var transaction = new Transaction(tableManager);
transaction.Begin(IsolationLevel.ReadCommitted);

try
{
    userTable.Insert(user1);
    userTable.Insert(user2);
    userTable.Insert(user3);
    
    transaction.Commit();
    Console.WriteLine("所有操作成功提交");
}
catch (Exception ex)
{
    transaction.Rollback();
    Console.WriteLine($</div>"操作失败,已回滚: {ex.Message}");
}

关于事务处理的详细用法,请查阅事务处理

6.6.2 批量操作优先

对于大量数据的操作,优先使用批量方法:

// 推荐:批量插入
userTable.InsertAll(users);

// 不推荐:逐个插入
foreach (var user in users)
{
    userTable.Insert(user);
}

6.6.3 错误处理

始终进行错误处理:

try
{
    userTable.Insert(user);
}
catch (Exception ex)
{
    Console.WriteLine($"插入失败: {ex.Message}");
    // 处理错误
}

6.6.4 资源管理

使用 using 语句管理资源:

using var userTable = tableManager.Table<User>();
// 使用表对象
// 自动释放资源

总结

本章介绍了 ORMX 框架的 CRUD 操作,包括数据的插入、查询、更新和删除。ORMX 提供了简洁的 API,支持单个操作和批量操作,能够满足大多数业务场景的需求。对于 MongoDB,ORMX 提供了专门的 CRUD 操作支持,包括 _id 字段映射、文档查询和批量操作等。合理使用批量操作可以显著提升性能,使用事务可以确保数据一致性。

扩展思考

在高并发场景下,如何处理数据的并发修改问题?是否需要引入乐观锁或悲观锁机制?对于大数据量的删除操作,如何避免锁表和性能问题?在分布式系统中,如何保证跨节点的数据一致性?这些问题值得在深入使用 ORMX 后进一步思考。