Linq Extension Method

I often have to limit SELECT with fields like publishStart , publishEnd , active

I have these fields in several different tables. Therefore, only rows that should be selected

 a: active == true; b: publishStart < now; c: publishEnd > now; 

So for example:

 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)); 

This is a little longer, so I wonder if it is possible to create (extension?) - a method like:

 db.myTable.SingleOrDefault(a => (a.ID == _theID).isActive() 

where isActive() provides three lines of the above snippet.

How can i do this? Is there a better way to clear the code?

+7
source share
3 answers

To define an extension, you need a static class. You can put this in any namespace you like, just remember to include it in your applications.

 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); } } 

Pay attention to YourEntityType . This is used to ensure that the method is aware of the existence of publishStart , publishEnd and active . It should be either a class that implements these fields, or a contract (interface) that defines them.

Then you would call it like this:

 var item = db.myTable.Active().SingleOrDefault(...); 

Read more about extension methods here: http://msdn.microsoft.com/en-us/library/bb383977.aspx


Since there are a lot of comments around the world, I'm going to add a brief description of the interface solution here ...

It is not clear whether or not there is a common implementation for the three filtered fields or the interface for defining them. If not, then for the above, you will not:

  • The base class that implements these fields. In this case, you replace YourEntityType with YourBaseEntityType .
  • Interface for defining fields. In this case, you need your classes to implement fields. If classes are automatically generated (for example, the entity framework model / db), you can implement partial classes using their interface. In this case, you replace YourEntityType with IYourContract .
+13
source

Just define an interface like this

 public interface IHaveAActivityPeriod { Boolean active { get; } DateTime? publishStart { get; } DateTime? publishEnd { get; } } 

and add it to all relevant classes.

 public class Foo : IHaveAActivityPeriod { [...] } public class Bar : IHaveAActivityPeriod { [...] } 

Now you can use this extension method

 public static class Extensions { public static Boolean IsActive(this IHaveAActivityPeriod item) { var now = DateTime.Now; return item.active && (item.publishStart <= now) (!item.publishEnd.HasValue || (item.publishEnd > now)); } } 

for each instance that implements IHaveAActivityPeriod .

 var foo = new Foo(); var isFooActive = foo.IsActive(); var bar = new Bar(); var isBarActive = bar.IsActive(); 

I completely missed the opportunity to build an extension method that filters the sequence instead of looking at one object at a time. Just take the extension method from flem, respond to the throw in the interface as a type constraint.

 public static class Extensions { public IQueryable<T> IsActive<T>(this IQueryable<T> sequence) where T : IHaveAActivityPeriod { return source.Where(item => item.active && (item.publishStart <= now) && (!item.publishEnd.HasValue || (item.publishEnd > now)); } } 
+4
source
 public static class Extensions { public static IEnumerable<MyClass> isActive(this IEnumerable<MyClass> list) { return list.Where(a => ((a.publishEnd > DateTime.Now) || (a.publishEnd == null)) && ((a.publishStart <= DateTime.Now) || (a.publishStart == null)) && a.active == true); } } 
+3
source

All Articles