我正在尝试使用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在大多数情况下都是值类型(主要是int
,long
,Guid
),因此它与我的不匹配需要。并且通用约束where TId: struct
不会使其编译。我理解发生这种情况的原因(感谢this thread)。
实体的界面是
public interface IHasAnIdField<TId>
{
TId Id { get; }
}
我无法使用.Equal(..)
调用或任何EqualityComparer
,因为SQLinq工具不会处理表达式树中的方法调用。
如何通知编译器我的TId与==
运算符兼容?
答案 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;
}