Entity Framework中如何实现含相同属性DbSet的通用校验方法
解决方案
以下是三种可直接落地的实现方案,按推荐优先级排序:
方案1:公共接口约束(推荐)
这是最安全、性能最优的方案,编译期即可校验实体合法性,无运行时风险。
- 定义统一的带
PartId字段的公共接口:
public interface IHasPartId { int PartId { get; } }
- 所有包含
PartId字段的实体类都实现该接口:
// 示例实体 public class ProductLink : IHasPartId { public int PartId { get; set; } // 其他实体字段... }
- 编写泛型通用校验方法,添加接口约束:
private async Task CheckLinkExistAsync<T>(int idForLookUp, string errorMsg, DbSet<T> table, CancellationToken cancellationToken) where T : class, IHasPartId { bool linkExist = await table.AnyAsync(model => model.PartId == idForLookUp, cancellationToken).ConfigureAwait(false); if (linkExist) { throw new InvalidOperationException(errorMsg); } }
调用示例:
await CheckLinkExistAsync(parameters.PartId, "关联已存在", dbContext.ProductLinks, cancellationToken);
方案2:动态构造表达式树
如果不方便修改现有实体类添加接口,可以用表达式树动态生成查询条件,无需改动实体定义:
private async Task CheckLinkExistAsync<T>(int idForLookUp, string errorMsg, DbSet<T> table, CancellationToken cancellationToken) where T : class { // 动态构造 x => x.PartId == idForLookUp 的查询表达式 var parameterExp = Expression.Parameter(typeof(T), "model"); var partIdPropExp = Expression.Property(parameterExp, "PartId"); var compareValueExp = Expression.Constant(idForLookUp); var equalExp = Expression.Equal(partIdPropExp, compareValueExp); var predicate = Expression.Lambda<Func<T, bool>>(equalExp, parameterExp); bool linkExist = await table.AnyAsync(predicate, cancellationToken).ConfigureAwait(false); if (linkExist) { throw new InvalidOperationException(errorMsg); } }
注意:该方案没有编译期校验,如果传入的实体类不存在PartId字段,会在运行时抛出异常。
方案3:原生SQL查询(仅做备选)
如果是简单场景,也可以直接拼接原生SQL执行查询,适配所有带对应字段的表:
private async Task CheckLinkExistAsync(int idForLookUp, string errorMsg, string tableName, CancellationToken cancellationToken) { var exist = await _dbContext.Database .SqlQueryRaw<int>($"SELECT 1 FROM `{tableName}` WHERE PartId = {{0}} LIMIT 1", idForLookUp) .AnyAsync(cancellationToken); if (exist) { throw new InvalidOperationException(errorMsg); } }
注意:该方案需要手动处理表名映射,存在SQL注入风险,必须使用参数化查询,不推荐优先使用。
内容的提问来源于stack exchange,提问作者Maykal Droshev
相关产品推荐
相关产品推荐

