我正在尝试扩展SqlMethods.Like方法以支持属性名而不是属性值,我编写了以下扩展方法:
public static bool Like(this object obj, string propertyName, string pattern)
{
var properties = obj.GetType().GetProperties().Select(p => p.Name);
if(!properties.Contains(propertyName))
throw new Exception(string.Format("Object does not contain property:{0}", propertyName));
return SqlMethods.Like(obj.GetType().GetProperty(propertyName).GetValue(obj, null).ToString(), pattern);
}
但是该方法会抛出以下异常: 方法'Boolean Like(System.Object,System.String,System.String)'没有支持的SQL转换。
如何编写带有事务的扩展方法来支持SQL?
答案 0 :(得分:1)
我从RichardD找到了这个答案,这正是答案。为了清晰起见,重新发布,但原文链接如下。
using System;
using System.Linq;
using System.Linq.Expressions;
public static class Extensions
{
public static IQueryable<T> WhereLike<T>(this IQueryable<T> source, string propertyName, string pattern)
{
if (null == source) throw new ArgumentNullException("source");
if (string.IsNullOrEmpty(propertyName)) throw new ArgumentNullException("propertyName");
var a = Expression.Parameter(typeof(T), "a");
var prop = Expression.Property(a, propertyName);
var body = Expression.Call(typeof(SqlMethods), "Like", null, prop, Expression.Constant(pattern));
var fn = Expression.Lambda<Func<T, bool>>(body, a);
return source.Where(fn);
}
}
...
.WhereLike("Description", "%a%b%c%"));
该解决方案使用表达式树,但所有高级LinqToSql操作都需要熟悉它。
答案 1 :(得分:0)
在SqlMethods.Like实际执行的内容中,您想要做什么似乎没有意义。传入类的属性时,实际上是在告诉它将其转换为SQL查询中的equivelent字段。 e.g。
var result = from names in db.Names
where SqlMethods.Like(names.FullName, '%Smith%')
select names;
会转换为:
SELECT *
FROM Names
WHERE Fullname LIKE '%Smith%'
(在实践中,使用参数和sp_executeSQL会有所不同,但是它会做到这一点。)
如果你想传递一个属性的名称,这在SQL方面意味着什么,从概念上来说,这是没有意义的。
SELECT *
FROM Names
WHERE --what would go here-- LIKE '%Smith%'
因此,您将无法创建创建无意义SQL的Linq To SQL方法。
你实际上想要做什么,你可能会以错误的方式解决这个问题。
编辑:嗯,从你的评论我想我明白你想要做什么,在本质上,你希望能够指定你在运行时进行LIKE比较的列。你不能完全这样做。您可以使用使用动态SQL的存储过程并为该列获取字符串参数。然后,您可以将其作为数据上下文类的方法公开。