Linq声明中的扩展方法

时间:2013-05-02 11:54:18

标签: asp.net-mvc-3 linq entity-framework-4

请参阅以下内容:

public Content GetContentByPageTitle(string pageTitle)
{
    return _db.Contents.FirstOrDefault(
            x => hnUrlHelper.UrlSafe(x.PageTitle).Equals(pageTitle)
        );
}


public class hnUrlHelper
{
    public static string UrlSafe(string value)
    {
        if (!string.IsNullOrEmpty(value))
        {
            value = value.Replace("Š", "s");

            value = value.Trim().ToLower();

            value = value.Replace(" ", "-");

            value = Regex.Replace(value, @"[^A-Za-z0-9-_]", "");

            return value.Trim().ToLower();
        }
        return string.Empty;
    }
}
  '/'应用程序中的服务器错误。           LINQ to Entities无法识别方法'System.String UrlSafe(System.String)'方法,而且此方法无法翻译   进入商店表达。

     

描述:未处理的异常   在执行当前Web请求期间发生。请   查看堆栈跟踪以获取有关错误和位置的更多信息   它起源于代码。

     

异常详细信息:   System.NotSupportedException:LINQ to Entities无法识别   方法'System.String UrlSafe(System.String)'方法,以及此方法   无法翻译成商店表达。

     

来源错误:

我正在尝试在Linq语句中找出UrlSafe方法。这显示如下错误。 请问有人知道如何使用这个吗?

2 个答案:

答案 0 :(得分:0)

该异常告诉您,您的方法无法转换为SQL。在这种情况下,无法修复,因为该方法使用的Regex也无法转换为SQL。

修复此类异常的常用方法是使用返回表达式的属性或方法:

Expression<Func<Content,bool>> EqualsUrl(string url)
{
    return c => c.PageTitle.Replace("Š", "s") == url;
}

这样称呼:

_db.Contents.FirstOrDefault(EqualsUrl(pageTitle))

只要您使用ReplaceToLowerTrim以及EF 可以转换为SQL的类似方法,您就可以了。但是,如上所述,Regex是这里的表演者。

答案 1 :(得分:0)

你可以在大多数情况下使用扩展方法,但我认为你不能为正则表达式部分做些什么。

我能接近的最好就是那样。

public static T FirstOrDefaultUrlSafe<T>(this IQueryable<T> queryable, Expression<Func<T, string>> propertyExpression, string pageTitle)
        {
            var parameter = propertyExpression.Parameters[0];
            var propertyName = (propertyExpression.Body as MemberExpression).Member.Name;
            Expression body = parameter;
            body = Expression.Property(body, propertyName);
            body = Expression.Call(body, "Replace", null, new[] { Expression.Constant("Š"), Expression.Constant("s") });
            body = Expression.Call(body, "ToLower", null);
            body = Expression.Call(body, "Trim", null);
            body = Expression.Call(body, "Replace", null, new[] { Expression.Constant(" "), Expression.Constant("-") });
            body = Expression.Equal(body, Expression.Constant(pageTitle));
            var lambda = Expression.Lambda<Func<T, bool>>(body, new[] { parameter });
            return queryable.FirstOrDefault(lambda);
        }

用于您的情况:

return _db.Contents.FirstOrDefaultUrlSafe(x => x.PageTitle, pageTitle)