我试图使用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与==
操作符兼容?
您可以手动构建表达式:
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;
}