Querying Entities Interface

Querying an entity from a database could be a tedious job. At most time, we do not have an interface to easily query a collection of entities. The following method uses cascade pattern to interface with the collections allowing us to query the object easily. It is also most useful if the requirements is to have a dynamic search query or we have a large entity object that we would like to attach few or more business rules. Otherwise, the following method could be

Let’s take our previous Customer object from the previous post.

public class Customer {
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public DateTime Dob { get; private set; }
    public string Email { get; private set; }
    public Customer(string firstName, string lastName, DateTime dob) { … }
    public void SetEmail(string email) { … }
}

Let’s say we want to find customers with “John” in the FirstName. We would normally do the following:

var customersWithJohnFirstName = _customerRepository.Query().Where(c => c.FirstName.Contains(“John”));

And now, we would like to continue our query to find a customer with the last name Smith. We would then do:

var johnSmithCustomersList = customersWithJohnFirstName.Where(c => c.LastName.Contains(“Smith”));

If we already knew that we were going to query both FirstName and LastName, we would normally do the following:

var johnSmithCustomerList = _customerRepository.Query().Where(c => c.FirstName.Contains(“John”) && c.LastName.Contains(“Smith”));

These are fine when the queries are simple and known. But when we require a more complex query, we would have many switch statements or if-then-else into the solution.

if (!string.isNullOrEmpty(firstName)) customerList = _customerRepository.Query().Where(c => c.FirstName.Contains(firstName));

if (!string.isNullOrEmpty(lastName)) customerList = customerList.Where(c => c.LastName.Contains(lastName));

Whilst the above method works, it could easily become difficult to manage as more attributes and business rules becomes applicable in the querying the customer repository.

In our case, we would like to have the following code instead of the above:

var customerList = SearchCustomer(_customerRepository)
     .FirstName(firstName)
     .LastName(lastName)
     .GetFilteredCollections();

The search interface for customer above defines explicitly the properties such as firstname and lastname. This is what the example in this blog will use. In this case, the interface acted as a facade on what is filterable in customer entity. It is however possible to create a custom property search based on a type, or even use that engine for the search itself.

Firstly, we instantiate our search interface. In this case, we want to return back the filtered collections.

public interface ISeach<t> where t: class {
    Enumerable<T> GetFilteredCollections();
}

In the search class, in this example we would be querying of a repo. In this case we will be passing the repository to the constructor and initializing it that way.

And the search class would be:

public class SearchCustomer : ISearch<Customer> {
    private IQueryable<Customer> _collections { get; }
    public Enumerable<Customer> GetFilteredCollections() => _collections.AsEnumerable();
    
    public SearchCustomer(CustomerRepository repo) => _collections = repo.Query();
    
    public SearchCustomer FirstName(string firstname) { 
        if (string.isNullOrEmpty(firstname)) return this; /// poor man string checker
        _collections = _collections.where(ct => ct.FirstName.contains(firstname)); ///Should be replaced with a dynamic search engine
       return this;
    }
    public SearchCustomer LastName(string lastname) { … }
}

The class above is very helpful to query the Customer entity. It provides an interface on what we could filter for the entity.

public SearchCustomer GetCustomersOldEnoughToDrink() { … }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s