Linq扩展方法

rei*_*ard 7 c# linq extension-methods linq-to-sql

我经常需要通过像领域的限制选择publishStart,publishEnd,active

我在几个不同的表中有这些字段.因此,只应选择行

a: active == true;
b: publishStart < now;
c: publishEnd > now;
Run Code Online (Sandbox Code Playgroud)

所以,例如:

db.myTable.SingleOrDefault(a => (a.ID == _theID 
          //now the active and start-end part:            
                      && ((a.publishEnd > DateTime.Now) || (a.publishEnd == null))
                      && ((a.publishStart <= DateTime.Now) || (a.publishStart == null))
                      && a.active == true));
Run Code Online (Sandbox Code Playgroud)

这有点冗长,所以我想知道是否有可能创建一个(扩展名?) - 方法,如:

db.myTable.SingleOrDefault(a => (a.ID == _theID).isActive()
Run Code Online (Sandbox Code Playgroud)

其中isActive()提供了上述代码段的3行.

我怎么能这样做?有没有更好的方法来清理代码?

Pau*_*ing 13

要定义扩展,您需要一个静态类.您可以将它放在您喜欢的任何名称空间中,只需记住将其包含在您的使用中.

public static class Extensions
{
    public static IQueryable<T> Active<T>(this IQueryable<T> source)
        where T : YourEntityType
    {
        return source.Where(a => ((a.publishEnd > DateTime.Now) || (a.publishEnd == null))
                          && ((a.publishStart <= DateTime.Now) || (a.publishStart == null))
                          && a.active == true);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意YourEntityType那里.这是用来确保方法是认识的存在publishStart,publishEndactive.这应该是实现这些字段的类或定义它们的契约(接口).

然后你会这样称呼它:

var item = db.myTable.Active().SingleOrDefault(...);
Run Code Online (Sandbox Code Playgroud)

有关扩展方法的更多信息,请访问:http://msdn.microsoft.com/en-us/library/bb383977.aspx


由于遍布各地的评论很多,我将在这里添加一个关于界面解决方案的简要说明......

在问题中是否存在三个过滤字段的通用实现或定义它们的接口尚不清楚.如果没有,为了上述工作,你不会:

  1. 实现这些字段的基类.在这种情况下,您将替换YourEntityTypeYourBaseEntityType.
  2. 用于定义字段的界面.在这种情况下,您需要让您的类实现字段.如果类是自动生成的(例如,实体框架模型/ db优先),那么您可以实现部分类,让它们实现接口.在这种情况下,你将替换YourEntityTypeIYourContract.

  • @Default这是一个问题,您是要对数据库执行查询,还是返回所有项目并使用C#代码进行过滤.在可能的情况下,DB中的过滤几乎总是可取的,但并不总是可行的. (2认同)