-
Notifications
You must be signed in to change notification settings - Fork 0
5. Specifications: data filters
Another task that often occurs in real projects is to clean requested data. Incoding Framework uses WhereSpecifications for convenient code writing and complying an encapsulation principle for cleaning data from Query. In the written code add a possibility to clean data from GetPeopleQuery by FirstName and LastName. First, add to Example.Domain -> Persistences -> Human.cs file abstract class Where and two classes into this abstract class: ByFirstName and ByLastName
``` namespace Example.Domain { #region << Using >>using System;
using System.Linq.Expressions;
using Incoding;
using Incoding.Data;
#endregion
public class Human : IncEntityBase
{
#region Properties
public virtual DateTime Birthday { get; set; }
public virtual string FirstName { get; set; }
public new virtual string Id { get; set; }
public virtual string LastName { get; set; }
public virtual Sex Sex { get; set; }
#endregion
#region Nested Classes
public class Map : NHibernateEntityMap<Human>
{
#region Constructors
protected Map()
{
IdGenerateByGuid(r => r.Id);
MapEscaping(r => r.FirstName);
MapEscaping(r => r.LastName);
MapEscaping(r => r.Birthday);
MapEscaping(r => r.Sex);
}
#endregion
}
public abstract class Where
{
#region Nested Classes
public class ByFirstName : Specification<Human>
{
#region Properties
readonly string firstName;
#endregion
#region Constructors
public ByFirstName(string firstName)
{
this.firstName = firstName;
}
#endregion
public override Expression<Func<Human, bool>> IsSatisfiedBy()
{
if (string.IsNullOrEmpty(this.firstName))
return null;
return human => human.FirstName.ToLower().Contains(this.firstName.ToLower());
}
}
public class ByLastName : Specification<Human>
{
#region Properties
readonly string lastName;
#endregion
#region Constructors
public ByLastName(string lastName)
{
this.lastName = lastName;
}
#endregion
public override Expression<Func<Human, bool>> IsSatisfiedBy()
{
if (string.IsNullOrEmpty(this.lastName))
return null;
return human => human.LastName.ToLower().Contains(this.lastName.ToLower());
}
}
#endregion
}
#endregion
}
public enum Sex
{
Male = 1,
Female = 2
}
}
<p>Now use the written specifications in GetPeopleQuery. .Or()/.And() relations allow to merge atomic specifications that helps to use the created specifications many times and fine-tune necessary data filters (in the example we use .Or() relation)</p>
<h6>GetPeopleQuery.cs with specs</h6>
namespace Example.Domain { #region << Using >>
using System.Collections.Generic;
using System.Linq;
using Incoding.CQRS;
using Incoding.Extensions;
#endregion
public class GetPeopleQuery : QueryBase<List<GetPeopleQuery.Response>>
{
#region Properties
public string Keyword { get; set; }
#endregion
#region Nested Classes
public class Response
{
#region Properties
public string Birthday { get; set; }
public string FirstName { get; set; }
public string Id { get; set; }
public string LastName { get; set; }
public string Sex { get; set; }
#endregion
}
#endregion
protected override List<Response> ExecuteResult()
{
return Repository.Query(whereSpecification: new Human.Where.ByFirstName(Keyword)
.Or(new Human.Where.ByLastName(Keyword)))
.Select(human => new Response
{
Id = human.Id,
Birthday = human.Birthday.ToShortDateString(),
FirstName = human.FirstName,
LastName = human.LastName,
Sex = human.Sex.ToString()
}).ToList();
}
}
}
<p>Finally, it only remains to modify Index.cshtml in order to add a search box, which uses a Keyword field for data cleaning while a request is being processed.</p>
<h6>Index.cshtml</h6>
@using Example.Domain @using Incoding.MetaLanguageContrib @using Incoding.MvcContrib @{ Layout = "~/Views/Shared/_Layout.cshtml"; }
@(Html.When(JqueryBind.InitIncoding) .AjaxGet(Url.Dispatcher().Query(new GetPeopleQuery { Keyword = Selector.Jquery.Id("Keyword") }).AsJson()) .OnSuccess(dsl => dsl.Self().Core().Insert.WithTemplateByUrl(Url.Dispatcher().AsView("~/Views/Home/HumanTmpl.cshtml")).Html()) .AsHtmlAttributes(new { id = "PeopleTable" }) .ToDiv())
@(Html.When(JqueryBind.Click) .AjaxGet(Url.Dispatcher().AsView("~/Views/Home/AddOrEditHuman.cshtml")) .OnSuccess(dsl => dsl.WithId("dialog").Behaviors(inDsl => { inDsl.Core().Insert.Html(); inDsl.JqueryUI().Dialog.Open(option => { option.Resizable = false; option.Title = "Add human"; }); })) .AsHtmlAttributes() .ToButton("Add new human"))
<br/>
<ul>
<li><a href="/IncodingSoftware/get-started/wiki/4.-CRUD">Previous</a></li>
<li><a href="/IncodingSoftware/get-started/wiki/6.-Unit-tests">Next</a></li>
</ul>