简体   繁体   English

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

[英]Use == operator with generic type in a Where Linq statement

I am trying to generate a SQL query (as a string) using the SQLinq library . 我正在尝试使用SQLinq库生成SQL查询(作为字符串)。 The code context is a generic class that creates the query with a Where clause in it. 代码上下文是一个泛型类,用于创建带有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;
}

Adding a where TId: class generic constraint resolves the problem but since my TId are in most cases value types (mainly int , long , Guid ) it does not match my needs. 添加一个where TId: class泛型约束来解决问题,但由于我的TId在大多数情况下是值类型(主要是intlongGuid ),它不符合我的需要。 And the generic constraint where TId: struct does not make it compile. 而且where TId: struct的通用约束不会使其编译。 I understand the reasons why this happens (thanks to this thread ). 我理解为什么会发生这种情况(感谢这个帖子 )。

The interface for the entity is 实体的接口是

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

I cannot use a .Equal(..) call or any EqualityComparer since a method call in the Expression tree is not handled by the SQLinq tool. 我不能使用.Equal(..)调用或任何EqualityComparer因为SQLinq工具不处理Expression树中的方法调用。

How can I inform the compiler that my TId is compatible with the == operator? 如何通知编译器我的TId与==运算符兼容?

You could build the expression manually: 您可以手动构建表达式:

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

You should be able to use the new DynamicSQLinq class. 您应该能够使用新的DynamicSQLinq类。 Some examples can be seen in the unit tests for it that SQLinq has. 在SQLinq的单元测试中可以看到一些例子。 In your case, it might look like: 在您的情况下,它可能看起来像:

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

I had a similar problem in EF, I got it working by adding the IEquatable interface constraint which causes it to use the strong typed Equals method. 我在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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM