在Where Linq语句中使用泛型==运算符

本文关键字:泛型 运算符 Where Linq 语句 | 更新日期: 2023-09-27 17:51:22

我试图使用SQLinq库生成SQL查询(作为字符串)。代码上下文是一个泛型类,用于创建包含Where子句的查询。

public string Get<TEntity, TId>(TId id)
    where TEntity: IHasAnIdField<TId>
{
    var query = new SQLinq<TEntity>();
    // The following statement does not compile due to error in lambda with "==" operator
    // "Operator '==' cannot be applied to operands of type 'TId' and 'TId'"
    query = query.Where((Expression<Func<TEntity, bool>>)(i => i.Id == id));
    var sql = query.ToSQL().ToQuery();
    return sql;
}

添加where TId: class通用约束解决了问题,但由于我的TId在大多数情况下是值类型(主要是int, long, Guid),它不符合我的需求。和通用约束where TId: struct不使它编译。我明白为什么会发生这种情况(感谢这个线程)。

实体的接口是

public interface IHasAnIdField<TId>
{
    TId Id { get; }
}

我不能使用.Equal(..)调用或任何EqualityComparer,因为表达式树中的方法调用不是由SQLinq工具处理的。

我如何通知编译器我的TId与==操作符兼容?

在Where Linq语句中使用泛型==运算符

您可以手动构建表达式:

public string Get<TEntity, TId>(TId id)
    where TEntity: IHasAnIdField<TId>
{
    var query = new SQLinq<TEntity>();
    // predicate: i => i.Id == id    
    var arg = Expression.Parameter(typeof(TEntity), "i");
    var predicate =
        Expression.Lambda<Func<TEntity, bool>>(
            Expression.Equal(
                Expression.Property(arg, "Id"),
                Expression.Constant(id))
            arg);

    query = query.Where(predicate);
    var sql = query.ToSQL().ToQuery();
    return sql;
}

您应该能够使用新的DynamicSQLinq类。在SQLinq的单元测试中可以看到一些例子。在您的例子中,它可能看起来像:

public string Get<TEntity, TId>(TId id)
where TEntity : IHasAnIdField<TId>
{
    var query = new DynamicSQLinq(typeof(TEntity).Name);
    query = query.Where("Id = @0", id);
    var sql = query.ToSQL().ToQuery();
    return sql;
}

我在EF中遇到了类似的问题,我通过添加IEquatable接口约束使其使用强类型Equals方法来使其工作。

<>之前 public string Get<TEntity, TId>(TId id) where TEntity: IHasAnIdField<TId>, IEquatable<TId> { var query = new SQLinq<TEntity>(); // The following statement does not compile due to error in lambda with "==" operator // "Operator '==' cannot be applied to operands of type 'TId' and 'TId'" query = query.Where((Expression>)(i => i.Id == id)); var sql = query.ToSQL().ToQuery(); return sql; }