在Where Linq语句中使用带有泛型类型的==运算符

时间:2014-03-21 14:48:59

标签: c# linq generics lambda operators

我正在尝试使用SQLinq library生成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在大多数情况下都是值类型(主要是intlongGuid),因此它与我的不匹配需要。并且通用约束where TId: struct不会使其编译。我理解发生这种情况的原因(感谢this thread)。

实体的界面是

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

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

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

3 个答案:

答案 0 :(得分:4)

您可以手动构建表达式:

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;
}

答案 1 :(得分:2)

您应该可以使用新的DynamicSQLinq课程。在SQLinq所具有的unit tests for it中可以看到一些例子。在您的情况下,它可能看起来像:

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;
}

答案 2 :(得分:1)

我在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;
}