|
|
// ============================================================================
|
|
|
// 【文件说明】HwAboutUsInfoDetailService.cs - 关于我们明细信息服务类
|
|
|
// ============================================================================
|
|
|
// 这个服务类负责处理"关于我们"模块的明细数据业务逻辑,包括:
|
|
|
// - 明细信息的 CRUD 操作
|
|
|
// - 与主信息的关联查询
|
|
|
//
|
|
|
// 【分层架构说明】
|
|
|
// Controller(控制器层)-> Service(服务层)-> Repository(数据访问层)
|
|
|
//
|
|
|
// 控制器只负责:接收请求、调用服务、返回响应
|
|
|
// 服务层负责:业务逻辑、数据组装、事务控制
|
|
|
// 数据访问层负责:数据库 CRUD 操作
|
|
|
//
|
|
|
// 【与 Java Spring Boot 的对比】
|
|
|
// Java Spring Boot:
|
|
|
// @Service
|
|
|
// public class HwAboutUsInfoDetailServiceImpl implements HwAboutUsInfoDetailService { ... }
|
|
|
//
|
|
|
// ASP.NET Core + Furion:
|
|
|
// public class HwAboutUsInfoDetailService : ITransient { ... }
|
|
|
//
|
|
|
// ITransient 是 Furion 的"生命周期接口",表示"瞬态服务":
|
|
|
// - 每次请求都创建新实例
|
|
|
// - 类似 Java Spring 的 @Scope("prototype")
|
|
|
//
|
|
|
// Furion 支持三种生命周期:
|
|
|
// - ITransient:瞬态,每次请求新实例
|
|
|
// - IScoped:作用域,同一请求内共享实例
|
|
|
// - ISingleton:单例,全局共享一个实例
|
|
|
// ============================================================================
|
|
|
|
|
|
namespace Admin.NET.Plugin.HwPortal;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 关于我们明细信息服务类。
|
|
|
/// <para>
|
|
|
/// 【C# 语法知识点 - 接口实现】
|
|
|
/// public class HwAboutUsInfoDetailService : ITransient
|
|
|
///
|
|
|
/// ITransient 是 Furion 框架的"标记接口"(Marker Interface)。
|
|
|
/// 它没有任何方法,只是用来标记服务的生命周期。
|
|
|
///
|
|
|
/// 对比 Java Spring:
|
|
|
/// Java Spring 用 @Service + @Scope 注解来定义服务:
|
|
|
/// @Service
|
|
|
/// @Scope("prototype") // 等价于 ITransient
|
|
|
/// public class HwAboutUsInfoDetailService { ... }
|
|
|
///
|
|
|
/// C# Furion 用接口来标记,更符合"接口隔离原则"。
|
|
|
/// </para>
|
|
|
/// <para>
|
|
|
/// 【SqlSugar ORM 数据访问】
|
|
|
/// 这个服务使用 ISqlSugarClient 进行数据库操作。
|
|
|
/// SqlSugar 是 .NET 生态中流行的 ORM 框架,类似于 Java 的 MyBatis-Plus。
|
|
|
///
|
|
|
/// 对比 Java MyBatis:
|
|
|
// Java MyBatis:
|
|
|
// @Mapper
|
|
|
// public interface HwAboutUsInfoDetailMapper {
|
|
|
// HwAboutUsInfoDetail selectById(@Param("id") Long id);
|
|
|
// }
|
|
|
//
|
|
|
// C# SqlSugar:
|
|
|
// _db.Queryable<HwAboutUsInfoDetail>().Where(...).FirstAsync();
|
|
|
//
|
|
|
// SqlSugar 的优势:
|
|
|
// - 强类型,编译期检查
|
|
|
// - Lambda 表达式,IDE 智能提示
|
|
|
// - 链式调用,代码更流畅
|
|
|
// - 性能优秀,接近原生 SQL
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
public class HwAboutUsInfoDetailService : ITransient
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// MyBatis 映射器名称。
|
|
|
/// <para>
|
|
|
/// 【C# 语法知识点 - const 常量】
|
|
|
/// const 是"编译期常量",值在编译时就确定了。
|
|
|
///
|
|
|
/// 对比 Java:
|
|
|
/// Java: private static final String MAPPER = "HwAboutUsInfoDetailMapper";
|
|
|
/// C#: private const string Mapper = "HwAboutUsInfoDetailMapper";
|
|
|
///
|
|
|
/// C# 的命名约定:
|
|
|
/// - const 通常用 PascalCase(首字母大写)
|
|
|
/// - Java 的 static final 通常用 UPPER_SNAKE_CASE
|
|
|
/// </para>
|
|
|
/// <para>
|
|
|
/// 【为什么保留这个常量?】
|
|
|
/// 虽然当前使用 SqlSugar,但保留了 XML Mapper 的回滚能力。
|
|
|
/// 这个常量用于指定 XML 文件中 mapper 的 namespace。
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
private const string Mapper = "HwAboutUsInfoDetailMapper";
|
|
|
|
|
|
/// <summary>
|
|
|
/// MyBatis 执行器。
|
|
|
/// <para>
|
|
|
/// 【依赖注入】
|
|
|
/// 通过构造函数注入,和控制器注入服务的方式一样。
|
|
|
///
|
|
|
/// HwPortalMyBatisExecutor 是自定义的执行器,封装了 MyBatis 风格的 SQL 执行逻辑。
|
|
|
/// 当前代码中已注释掉使用,但保留以备回滚。
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
private readonly HwPortalMyBatisExecutor _executor;
|
|
|
|
|
|
/// <summary>
|
|
|
/// SqlSugar 数据访问对象。
|
|
|
/// <para>
|
|
|
/// 【ISqlSugarClient 接口】
|
|
|
/// 这是 SqlSugar 的核心接口,提供数据库访问能力。
|
|
|
///
|
|
|
/// 对比 Java:
|
|
|
/// Java MyBatis: SqlSession 或 Mapper 接口
|
|
|
/// C# SqlSugar: ISqlSugarClient
|
|
|
///
|
|
|
/// 通过依赖注入获取,由框架在启动时配置并注册到 DI 容器。
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
private readonly ISqlSugarClient _db;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 构造函数(依赖注入)。
|
|
|
/// <para>
|
|
|
/// 【C# 语法知识点 - 构造函数】
|
|
|
/// public HwAboutUsInfoDetailService(HwPortalMyBatisExecutor executor, ISqlSugarClient db)
|
|
|
///
|
|
|
/// 对比 Java:
|
|
|
/// Java:
|
|
|
/// @Autowired
|
|
|
/// public HwAboutUsInfoDetailService(HwPortalMyBatisExecutor executor, ISqlSugarClient db) {
|
|
|
/// this.executor = executor;
|
|
|
/// this.db = db;
|
|
|
/// }
|
|
|
///
|
|
|
/// C#:
|
|
|
/// public HwAboutUsInfoDetailService(HwPortalMyBatisExecutor executor, ISqlSugarClient db)
|
|
|
/// {
|
|
|
/// _executor = executor;
|
|
|
/// _db = db;
|
|
|
/// }
|
|
|
///
|
|
|
/// C# 的改进:
|
|
|
/// 1. 不需要 @Autowired 注解,框架自动识别构造函数
|
|
|
/// 2. 使用 _executor 命名约定表示私有字段
|
|
|
/// 3. 可以使用主构造函数(C# 12+)进一步简化
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
/// <param name="executor">MyBatis 执行器(保留用于回滚)</param>
|
|
|
/// <param name="db">SqlSugar 数据访问对象</param>
|
|
|
public HwAboutUsInfoDetailService(HwPortalMyBatisExecutor executor, ISqlSugarClient db)
|
|
|
{
|
|
|
_executor = executor;
|
|
|
_db = db;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 根据明细ID查询关于我们明细信息。
|
|
|
/// <para>
|
|
|
/// 【方法命名约定】
|
|
|
/// Select + 实体名 + By + 主键名:根据主键查询单条记录
|
|
|
///
|
|
|
/// 对比 Java 若依:
|
|
|
/// 若依通常使用:selectXxxById、getXxxById
|
|
|
/// 这里使用:SelectXxxByXxxId,更符合 C# 的 PascalCase 命名规范
|
|
|
/// </para>
|
|
|
/// <para>
|
|
|
/// 【async/await 异步编程】
|
|
|
/// public async Task<HwAboutUsInfoDetail> Select...
|
|
|
///
|
|
|
/// 对比 Java:
|
|
|
/// Java:
|
|
|
/// public CompletableFuture<HwAboutUsInfoDetail> select...(...) { ... }
|
|
|
/// 或
|
|
|
/// public HwAboutUsInfoDetail select...(...) { ... } // 同步
|
|
|
///
|
|
|
/// C#:
|
|
|
/// public async Task<HwAboutUsInfoDetail> Select...(...) { ... }
|
|
|
///
|
|
|
/// async/await 的优势:
|
|
|
/// - 代码看起来像同步,但底层是异步
|
|
|
/// - 避免回调地狱
|
|
|
/// - 更好的性能(不阻塞线程)
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
/// <param name="usInfoDetailId">明细ID</param>
|
|
|
/// <returns>明细实体,不存在则返回 null</returns>
|
|
|
public async Task<HwAboutUsInfoDetail> SelectHwAboutUsInfoDetailByUsInfoDetailId(long usInfoDetailId)
|
|
|
{
|
|
|
// 【回滚注释说明】
|
|
|
// 这行注释说明如何回滚到 XML Mapper 方案:
|
|
|
// 只需取消注释下面这行,注释掉 SqlSugar 代码即可
|
|
|
// 这种设计保留了"后悔药",便于调试和问题排查
|
|
|
//
|
|
|
// 回滚到 XML 方案时可直接恢复:
|
|
|
// return await _executor.QuerySingleAsync<HwAboutUsInfoDetail>(Mapper, "selectHwAboutUsInfoDetailByUsInfoDetailId", new { usInfoDetailId });
|
|
|
|
|
|
// 【SqlSugar 查询语法】
|
|
|
// _db.Queryable<HwAboutUsInfoDetail>():创建一个针对 HwAboutUsInfoDetail 表的查询
|
|
|
// .Where(item => item.UsInfoDetailId == usInfoDetailId):添加 WHERE 条件
|
|
|
// .FirstAsync():执行查询,返回第一条记录,如果没有则返回 null
|
|
|
//
|
|
|
// 生成的 SQL 类似于:
|
|
|
// SELECT * FROM hw_about_us_info_detail WHERE UsInfoDetailId = @usInfoDetailId LIMIT 1
|
|
|
//
|
|
|
// 对比 Java MyBatis:
|
|
|
// Java: mapper.selectOne(new QueryWrapper<HwAboutUsInfoDetail>().eq("UsInfoDetailId", usInfoDetailId));
|
|
|
// C#: _db.Queryable<HwAboutUsInfoDetail>().Where(item => item.UsInfoDetailId == usInfoDetailId).FirstAsync();
|
|
|
//
|
|
|
// C# 的优势:Lambda 表达式是强类型的,拼写错误在编译期就能发现
|
|
|
return await _db.Queryable<HwAboutUsInfoDetail>()
|
|
|
.Where(item => item.UsInfoDetailId == usInfoDetailId)
|
|
|
.FirstAsync();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 查询关于我们明细列表。
|
|
|
/// <para>
|
|
|
/// 【动态查询条件构建】
|
|
|
/// 这个方法展示了如何根据输入参数动态构建查询条件。
|
|
|
/// 只有参数有值时,才添加对应的 WHERE 条件。
|
|
|
/// </para>
|
|
|
/// <para>
|
|
|
/// 【空合并运算符 ??】
|
|
|
/// input ?? new HwAboutUsInfoDetail()
|
|
|
///
|
|
|
/// 如果 input 为 null,则创建一个新的默认对象。
|
|
|
/// 这样可以避免后面的空引用异常。
|
|
|
///
|
|
|
/// 对比 Java:
|
|
|
/// Java: input != null ? input : new HwAboutUsInfoDetail();
|
|
|
/// C#: input ?? new HwAboutUsInfoDetail();
|
|
|
///
|
|
|
/// C# 更简洁!
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
/// <param name="input">查询条件</param>
|
|
|
/// <returns>明细列表</returns>
|
|
|
public async Task<List<HwAboutUsInfoDetail>> SelectHwAboutUsInfoDetailList(HwAboutUsInfoDetail input)
|
|
|
{
|
|
|
// 【防御性编程】
|
|
|
// 确保 query 不为 null,避免后续空引用异常
|
|
|
HwAboutUsInfoDetail query = input ?? new HwAboutUsInfoDetail();
|
|
|
|
|
|
// 回滚到 XML 方案时可直接恢复:
|
|
|
// return await _executor.QueryListAsync<HwAboutUsInfoDetail>(Mapper, "selectHwAboutUsInfoDetailList", query);
|
|
|
|
|
|
// 【SqlSugar WhereIF 动态条件】
|
|
|
// .WhereIF(condition, expression):只有当 condition 为 true 时,才添加 WHERE 条件
|
|
|
//
|
|
|
// 对比 Java MyBatis 的 XML:
|
|
|
// <if test="aboutUsInfoId != null">
|
|
|
// AND AboutUsInfoId = #{aboutUsInfoId}
|
|
|
// </if>
|
|
|
//
|
|
|
// C# SqlSugar 的 WhereIF 更直观,而且类型安全
|
|
|
//
|
|
|
// 【HasValue 可空类型检查】
|
|
|
// query.AboutUsInfoId.HasValue 检查可空 long? 是否有值
|
|
|
//
|
|
|
// 对比 Java:
|
|
|
// Java: query.getAboutUsInfoId() != null
|
|
|
// C#: query.AboutUsInfoId.HasValue
|
|
|
//
|
|
|
// 【string.IsNullOrWhiteSpace】
|
|
|
// 检查字符串是否为 null、空字符串 "" 或仅包含空白字符
|
|
|
//
|
|
|
// 对比 Java:
|
|
|
// Java: StringUtils.isBlank(str)(需要 Apache Commons Lang)
|
|
|
// C#: string.IsNullOrWhiteSpace(str)(内置)
|
|
|
//
|
|
|
// 【Contains 模糊查询】
|
|
|
// item.UsInfoDetailTitle.Contains(query.UsInfoDetailTitle)
|
|
|
// 生成 SQL:WHERE UsInfoDetailTitle LIKE '%xxx%'
|
|
|
//
|
|
|
// 【ToListAsync】
|
|
|
// 执行查询并返回列表,异步版本
|
|
|
return await _db.Queryable<HwAboutUsInfoDetail>()
|
|
|
.WhereIF(query.AboutUsInfoId.HasValue, item => item.AboutUsInfoId == query.AboutUsInfoId)
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.UsInfoDetailTitle), item => item.UsInfoDetailTitle.Contains(query.UsInfoDetailTitle))
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.UsInfoDetailDesc), item => item.UsInfoDetailDesc.Contains(query.UsInfoDetailDesc))
|
|
|
.WhereIF(query.UsInfoDetailOrder.HasValue, item => item.UsInfoDetailOrder == query.UsInfoDetailOrder)
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.UsInfoDetailPic), item => item.UsInfoDetailPic == query.UsInfoDetailPic)
|
|
|
.ToListAsync();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 新增关于我们明细信息。
|
|
|
/// <para>
|
|
|
/// 【插入操作返回值】
|
|
|
/// 返回 int 表示影响行数(1 表示成功,0 表示失败)。
|
|
|
/// 这是为了兼容原有 XML Mapper 的返回类型。
|
|
|
/// </para>
|
|
|
/// <para>
|
|
|
/// 【时间戳处理】
|
|
|
/// HwPortalContextHelper.Now() 获取当前时间。
|
|
|
/// 使用助手类的好处:
|
|
|
/// 1. 可以统一控制时间来源(如测试时 mock)
|
|
|
/// 2. 可以统一时区处理
|
|
|
/// 3. 便于后续扩展(如使用 UTC 时间)
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
/// <param name="input">明细数据</param>
|
|
|
/// <returns>影响行数(1成功,0失败)</returns>
|
|
|
public async Task<int> InsertHwAboutUsInfoDetail(HwAboutUsInfoDetail input)
|
|
|
{
|
|
|
// 【审计字段自动填充】
|
|
|
// CreateTime 由代码自动设置,不需要前端传递
|
|
|
// 这是常见的"审计字段"处理模式
|
|
|
input.CreateTime = HwPortalContextHelper.Now();
|
|
|
|
|
|
// 回滚到 XML 方案时可直接恢复:
|
|
|
// long identity = await _executor.InsertReturnIdentityAsync(Mapper, "insertHwAboutUsInfoDetail", input);
|
|
|
|
|
|
// 【SqlSugar 插入语法】
|
|
|
// _db.Insertable(input):创建一个插入操作
|
|
|
// .ExecuteReturnEntityAsync():执行插入并返回插入后的实体(包含自增主键)
|
|
|
//
|
|
|
// 对比 Java MyBatis:
|
|
|
// Java:
|
|
|
// mapper.insert(input);
|
|
|
// Long identity = input.getUsInfoDetailId(); // 需要配置 useGeneratedKeys
|
|
|
//
|
|
|
// C#:
|
|
|
// var entity = await _db.Insertable(input).ExecuteReturnEntityAsync();
|
|
|
// input.UsInfoDetailId = entity.UsInfoDetailId;
|
|
|
//
|
|
|
// C# 的优势:ExecuteReturnEntityAsync 直接返回插入后的完整实体
|
|
|
HwAboutUsInfoDetail entity = await _db.Insertable(input).ExecuteReturnEntityAsync();
|
|
|
|
|
|
// 【回填主键】
|
|
|
// 将生成的自增主键回填到输入对象
|
|
|
// 这样调用方可以获取到新插入记录的 ID
|
|
|
input.UsInfoDetailId = entity.UsInfoDetailId;
|
|
|
|
|
|
// 【返回影响行数】
|
|
|
// 为了兼容原有接口,返回 1 或 0
|
|
|
// 而不是返回主键值
|
|
|
return input.UsInfoDetailId > 0 ? 1 : 0;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 更新关于我们明细信息。
|
|
|
/// <para>
|
|
|
/// 【更新策略】
|
|
|
/// 这里使用"先查询后更新"的策略:
|
|
|
/// 1. 先根据 ID 查询现有记录
|
|
|
/// 2. 如果记录不存在,返回 0
|
|
|
/// 3. 只更新输入对象中不为 null 的字段
|
|
|
/// 4. 执行更新
|
|
|
///
|
|
|
/// 这种策略的好处:
|
|
|
/// - 避免全字段更新(减少并发冲突)
|
|
|
/// - 可以处理部分字段更新的场景
|
|
|
/// - 保持原有数据不变
|
|
|
/// </para>
|
|
|
/// <para>
|
|
|
/// 【对比 Java 若依】
|
|
|
/// 若依通常使用 MyBatis 的 <if> 标签实现动态更新:
|
|
|
/// <update id="updateXxx">
|
|
|
/// UPDATE table
|
|
|
/// <set>
|
|
|
/// <if test="field1 != null">field1 = #{field1},</if>
|
|
|
/// <if test="field2 != null">field2 = #{field2},</if>
|
|
|
/// </set>
|
|
|
/// WHERE id = #{id}
|
|
|
/// </update>
|
|
|
///
|
|
|
/// C# 这里手动控制,更灵活但需要更多代码。
|
|
|
/// 也可以用 SqlSugar 的 .UpdateColumns() 实现类似效果。
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
/// <param name="input">更新的数据</param>
|
|
|
/// <returns>影响行数</returns>
|
|
|
public async Task<int> UpdateHwAboutUsInfoDetail(HwAboutUsInfoDetail input)
|
|
|
{
|
|
|
// 【审计字段更新】
|
|
|
// 自动设置更新时间
|
|
|
input.UpdateTime = HwPortalContextHelper.Now();
|
|
|
|
|
|
// 回滚到 XML 方案时可直接恢复:
|
|
|
// return await _executor.ExecuteAsync(Mapper, "updateHwAboutUsInfoDetail", input);
|
|
|
|
|
|
// 【查询现有记录】
|
|
|
// 先查出数据库中的当前记录
|
|
|
// 如果记录不存在,返回 0 表示更新失败
|
|
|
HwAboutUsInfoDetail current = await SelectHwAboutUsInfoDetailByUsInfoDetailId(input.UsInfoDetailId ?? 0);
|
|
|
if (current == null)
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
// 【字段级更新】
|
|
|
// 只更新输入对象中明确有值的字段
|
|
|
// null 值表示"不更新此字段"
|
|
|
//
|
|
|
// 这种设计支持部分更新(PATCH 语义)
|
|
|
// 对比全量更新(PUT 语义),更灵活
|
|
|
|
|
|
// 更新关联主表ID
|
|
|
if (input.AboutUsInfoId.HasValue)
|
|
|
{
|
|
|
current.AboutUsInfoId = input.AboutUsInfoId;
|
|
|
}
|
|
|
|
|
|
// 更新标题(null 检查避免覆盖为 null)
|
|
|
if (input.UsInfoDetailTitle != null)
|
|
|
{
|
|
|
current.UsInfoDetailTitle = input.UsInfoDetailTitle;
|
|
|
}
|
|
|
|
|
|
// 更新描述
|
|
|
if (input.UsInfoDetailDesc != null)
|
|
|
{
|
|
|
current.UsInfoDetailDesc = input.UsInfoDetailDesc;
|
|
|
}
|
|
|
|
|
|
// 更新排序号
|
|
|
if (input.UsInfoDetailOrder.HasValue)
|
|
|
{
|
|
|
current.UsInfoDetailOrder = input.UsInfoDetailOrder;
|
|
|
}
|
|
|
|
|
|
// 更新图片
|
|
|
if (input.UsInfoDetailPic != null)
|
|
|
{
|
|
|
current.UsInfoDetailPic = input.UsInfoDetailPic;
|
|
|
}
|
|
|
|
|
|
// 更新创建时间(通常不应该更新,但保留兼容)
|
|
|
if (input.CreateTime.HasValue)
|
|
|
{
|
|
|
current.CreateTime = input.CreateTime;
|
|
|
}
|
|
|
|
|
|
// 更新创建人
|
|
|
if (input.CreateBy != null)
|
|
|
{
|
|
|
current.CreateBy = input.CreateBy;
|
|
|
}
|
|
|
|
|
|
// 【必须更新的字段】
|
|
|
// UpdateTime 每次更新都必须更新
|
|
|
current.UpdateTime = input.UpdateTime;
|
|
|
|
|
|
// 更新更新人
|
|
|
if (input.UpdateBy != null)
|
|
|
{
|
|
|
current.UpdateBy = input.UpdateBy;
|
|
|
}
|
|
|
|
|
|
// 【执行更新】
|
|
|
// _db.Updateable(current):创建更新操作
|
|
|
// .ExecuteCommandAsync():执行更新,返回影响行数
|
|
|
//
|
|
|
// 生成的 SQL 类似于:
|
|
|
// UPDATE hw_about_us_info_detail
|
|
|
// SET AboutUsInfoId = @AboutUsInfoId, UsInfoDetailTitle = @UsInfoDetailTitle, ...
|
|
|
// WHERE UsInfoDetailId = @UsInfoDetailId
|
|
|
return await _db.Updateable(current).ExecuteCommandAsync();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 批量删除关于我们明细信息。
|
|
|
/// <para>
|
|
|
/// 【批量删除】
|
|
|
/// 根据 ID 数组批量删除记录。
|
|
|
/// </para>
|
|
|
/// <para>
|
|
|
/// 【IN 语句】
|
|
|
// .In(usInfoDetailIds) 生成 SQL:WHERE UsInfoDetailId IN (1, 2, 3)
|
|
|
//
|
|
|
// 对比 Java MyBatis:
|
|
|
// Java XML:
|
|
|
// <foreach collection="array" item="id" open="(" separator="," close=")">
|
|
|
// #{id}
|
|
|
// </foreach>
|
|
|
//
|
|
|
// C# SqlSugar:
|
|
|
// .In(usInfoDetailIds)
|
|
|
//
|
|
|
// C# 更简洁!
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
/// <param name="usInfoDetailIds">明细ID数组</param>
|
|
|
/// <returns>影响行数</returns>
|
|
|
public async Task<int> DeleteHwAboutUsInfoDetailByUsInfoDetailIds(long[] usInfoDetailIds)
|
|
|
{
|
|
|
// 回滚到 XML 方案时可直接恢复:
|
|
|
// return await _executor.ExecuteAsync(Mapper, "deleteHwAboutUsInfoDetailByUsInfoDetailIds", new { array = usInfoDetailIds });
|
|
|
|
|
|
// 【SqlSugar 删除语法】
|
|
|
// _db.Deleteable<HwAboutUsInfoDetail>():创建删除操作
|
|
|
// .In(usInfoDetailIds):添加 IN 条件
|
|
|
// .ExecuteCommandAsync():执行删除,返回影响行数
|
|
|
//
|
|
|
// 生成的 SQL:
|
|
|
// DELETE FROM hw_about_us_info_detail WHERE UsInfoDetailId IN (@p1, @p2, @p3)
|
|
|
//
|
|
|
// 【注意】这里是物理删除,不是软删除
|
|
|
// 如果需要软删除,应该使用 Updateable 更新 IsDelete 字段
|
|
|
return await _db.Deleteable<HwAboutUsInfoDetail>()
|
|
|
.In(usInfoDetailIds)
|
|
|
.ExecuteCommandAsync();
|
|
|
}
|
|
|
}
|