Linq查询中的字符串扩展方法

时间:2013-08-20 10:01:45

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

如何在linq查询中使用字符串扩展方法:

public NewsType GetNewsType(string name)
{
   var newsType = db.NewsTypes.FirstOrDefault(x => x.Name.ToFriendlyUrl() ==  
                                              name.ToFriendlyUrl());
   return newsType;
}

上次查询x.Name.ToFriendlyUrl()不允许。有谁知道如何实现它。

4 个答案:

答案 0 :(得分:1)

var newsType = db.NewsTypes.FirstOrDefault(
          x => x.Name.ToFriendlyUrl() == name.ToFriendlyUrl());

无法在Entity Framework中完成。 ToFriendlyUrl是一种扩展方法。这是“客户端”计算机中的东西。查询将在SQL服务器上执行。 SQL服务器没有ToFriendlyUrl函数。

“标准”解决方案是将名为FriendlyName的第二列保存为ToFriendlyUrl()的预先计算版本,以便您的查询变为:

var friendlyName = name.ToFriendlyUrl();
var newsType = db.NewsTypes.FirstOrDefault(
          x => x.FriendlyName == friendlyName);

答案 1 :(得分:1)

假设NewsTypesIQueryable,这是实体框架无法将扩展方法转换为SQL的结果(应该如何?)。除非您可以将谓词重写为Entity Framework可以转换为SQL的内容,否则您必须执行查询客户端:

public NewsType GetNewsType(string name)
{
   var newsType = db.NewsTypes.AsEnumerable().FirstOrDefault(x => x.Name.ToFriendlyUrl() == name.ToFriendlyUrl());
   return newsType;
}

注意AsEnumerable()之前添加了FirstOrDefault的方法。不幸的是,这可能会将NewsTypes返回的所有行从服务器拉到客户端,因此可能会非常昂贵。

答案 2 :(得分:1)

LINQ查询确实允许使用扩展方法,而且LINQ methods本身也是作为扩展方法实现的。

然而,在LINQ-to-SQL或LINQ-to-Entities查询中使用扩展方法(或大多数其他方法)是另一个问题。这些查询实际上并不在C#代码中运行,但它们被视为转换为SQL的表达式。即。

db.News.Where(x => x.Published).Select(x => x.Name)

被翻译为SQL语句

Select Name 
From News
Where Published = 1

并将结果返回给C#代码。

由于无法将ToFriendlyUrl()方法转移到SQL,因此您的代码会抛出错误。

基本上,你有两个解决方案/解决方法。一种是将调用转换为可以转换为SQL的形式,例如如果ToFriendlyUrl()方法只是:

public static string ToFriendlyURL(this string value)
{
    return value.ToLower();
}

您可以在LINQ调用中内联该代码,这样可行。但是,如果方法更复杂,那么您唯一的解决方案就是从基础中获取数据,然后在C#端处理它:

var newsTypeQuery = db.NewsTypes.Where(x => // other conditions, if any);
var newsTypes = newsTypes.ToList(); //forces execution of the query
                                    // the result is now a C# list
var newsType = newsTypes.FirstOrDefault(x => 
                                 x.Name.ToFriendlyUrl() == name.ToFriendlyUrl());

答案 3 :(得分:0)

相反尝试这样

public NewsType GetNewsType(string name)
{
   var newsType = db.NewsTypes.FirstOrDefault(x => x.Name == name).ToFriendlyUrl();
   return newsType;
}