Introducing Specification Pattern

In this lesson, we're going to implement Specification Pattern

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the The newline Guide to Fullstack ASP.NET Core and React course and can be unlocked immediately with a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to The newline Guide to Fullstack ASP.NET Core and React with a single-time purchase.

Thumbnail for the \newline course The newline Guide to Fullstack ASP.NET Core and React
  • [00:00 - 00:07] Our controllers are working but they don't return the navigation properties. Coarse repository just returned the courses.

    [00:08 - 00:17] Category repository returns the categories. As we discussed, we cannot use include method because we are not sure of the entity type.

    [00:18 - 00:22] This is where specification pattern comes to our rescue. You can simply create a condition.

    [00:23 - 00:34] For example, you want all the courses which are below $10 and pass that specification to the tool is async method. The method will keep the specification in mind while making that query.

    [00:35 - 00:38] Don't get confused. Let's see how to use them.

    [00:39 - 00:50] First of all, let's get rid of it and inside the entity project, we need to create another folder. Let's call it specifications.

    [00:51 - 01:02] Inside this folder, let's create a new interface which will be called i specification. It will take a type as well.

    [01:03 - 01:09] So what we can do is write t inside curly brackets. We now need to create some generic methods.

    [01:10 - 01:15] The first method will be an expression which will take a function. So let's write that.

    [01:16 - 01:25] It will be an expression and that expression will take a function. Function will take a type.

    [01:26 - 01:42] So we can write inside curly brackets, t and it will return a boolean. We can call this method criteria followed by our getter.

    [01:43 - 01:50] We are writing t because we are using it inside our generic repository. So we are not sure about the type here either.

    [01:51 - 02:05] And we are calling it criteria because we are going to write a query which will ask our database what to get. For example, if we want a cost with price below $10, we can write a criteria and we will get the data whenever the criteria is met.

    [02:06 - 02:12] We need to import it. So let's import expression using system.linked.expressions.

    [02:13 - 02:17] Let's import funk using system. Now let's write our second criteria.

    [02:18 - 02:23] This criteria will be equal to the include statement that we have created. This will be a list of expression.

    [02:24 - 02:44] So we can write list of expression and the same thing expression will take a funk of type t. But this time it will return an object because when we are using the include statement, we are returning the objects, right?

    [02:45 - 02:53] So we can simply call it include followed by get. Let's import list using system.collection.generics.

    [02:54 - 02:58] And this is it. This might look very confusing right now.

    [02:59 - 03:05] And I agree. Once we implement it using the actual expression, it will appear very straightforward.

    [03:06 - 03:24] Like we created repositories which implemented our interfaces, we will create a base class which will implement this I specification. So here inside these specifications folder, let's create a new class and we will call it base specification.

    [03:25 - 03:32] This is generic. So it will take type t and it will derive from I specification of type t.

    [03:33 - 03:41] Let's implement it using quick fix. This will generate the methods with not implemented exception.

    [03:42 - 03:58] Since we are going to implement this, we can take this statement off and we can replace it with get. We also need to generate a constructor, but it should not be empty.

    [03:59 - 04:13] So I will use quick fix and generate constructor. It has both our methods, but we do not want to initialize it with include because not every time we are going to use the include method.

    [04:14 - 04:22] So what we can do is take that out from here. And here as well, we should initialize our list with empty list.

    [04:23 - 04:36] So I can make a new empty list here, which will be of same functionality. This list again is an expression which takes a function and returns an object.

    [04:37 - 04:47] We need this because we need something to add our list into. Since we are not adding it to our constructor, we can create a method which will help us add an include statement.

    [04:48 - 05:01] So what we'll do is below this, I can create a protected method so that every class derived from this can use this method. So it won't return anything so it will be void.

    [05:02 - 05:12] Let's call it include method. This will take an expression as a parameter.

    [05:13 - 05:30] So what I can do is simply copy it and paste it here. And let's call it simply expression.

    [05:31 - 05:47] And inside this we can write include dot add and I will add this expression. The whole point of writing so much code is to add queries to our straightforward methods.

    [05:48 - 06:03] This might seem like a lot of work, but this is not something you're going to write for every repository unlike the include method, which needs to be added every time whenever we are making a call. This is writing once and using any time you want to fetch something similar.

    [06:04 - 06:06] So in the next lecture, let's take this process ahead.