Sony Arouje

a programmer's log

Posts Tagged ‘Entity

Lambda expression validation against Entity

leave a comment »

The system that I was building, I created a generic Record exist validator. What this does is check whether a specific record exist in the database. Say user can pass a Product code and check whether the Product exist in the database. In some scenario just checking a Product exist may not be sufficient, say while doing an invoice we should validate and raise error if a product is soft deleted but in some scenario we need to check whether the product exist nothing more. That means this custom status check should not implemented to the core Product exist validator. Developer should inject the custom Error condition logic based on the functionality he is working. This post explains the Custom Error conditions logic I implemented based on Lambda expression.

Lambda expression Validation

The easy way for a developer to write a Error condition using Lambda expression, pseudo code will be some thing like this.

(product=>product.isDeleted==true) then raise exception.

Initial 30 minutes I was thinking how to get the body of expression and validate the entity because we cannot directly apply Lambda expression to an entity like Product. When I go deeper into expression evaluation, I realize that I need more time than anticipated and might ended up with a complex functionality. This is what I did to solve this scenario.

  1. Add the entity to validate to a generic List
  2. Pass the lambda expression to Where() of the list.
  3. If the result count is greater than 0 raise the error.

see the code below.

public class ErrorCondition
{
    private object _criteria;
    private Exception _exceptionToRaise = null;

    public ErrorCondition IfTrue<T>(Func<T, bool> criteria) where T:class
    {
        _criteria = criteria;
        return this;
    }

    public void RaiseException(Exception exceptionToRaise)
    {
        this._exceptionToRaise = exceptionToRaise;
        return this;
    }

    internal void Validate<T>(T entity)
    {
        List<T> tmp = new List<T>();
        tmp.Add(entity);
        Func<T, bool> criteria = (Func<T, bool>)this._criteria;
        var result = tmp.Where<T>(criteria).ToList<T>();
        if (result.Count > 0)
        {
            if (_exceptionToRaise == null)
                throw new Exceptions.MaginusException("Error Condition is matching but 
                  no exception attached to ErrorCondition. Please set exception via 
                  RaiseException function.");
            throw _exceptionToRaise;
        }

    }
}

User can create a custom error condition as shown below.

ErrorCondition isDeletedCheckCondition = new ErrorCondition();
isDeletedCheckCondition.IfTrue<Product>(p => p.IsDeleted== true)
    .RaiseException(new Exception("Product is deleted"));

I created a class to group multiple error conditions user may need to add.

public class ErrorConditions
{
    IList<ErrorCondition> _errorConditions;
    public ErrorConditions()
    {
        _errorConditions = new List<ErrorCondition>();
    }

    public ErrorConditions Add(ErrorCondition condition)
    {
        this._errorConditions.Add(condition);
        return this;
    }

    internal void Validate<T>(T entity)
    {
        foreach (ErrorCondition errCondition in _errorConditions)
            errCondition.Validate<T>(entity);
    }
}

Now user can add multiple Error conditions as shown below.

ErrorConditions errorConditions = new ErrorConditions()
    .Add(new ErrorCondition().IfTrue<Product>(p => p.IsDeleted == true)
       .RaiseException(new Exception("Product is deleted and cannot be added")))
    .Add(new ErrorCondition().IfTrue<Product>(p => p.IsWithdrawn == true)
       .RaiseException(new Exception("Product is withdrawn.")));

Pass this errorConditions instance to Product Exist validator, Validator will call errorConditions.Validate<Product>(productToValidate) if the record exist in the database.

The key point to note here is, how we could evaluate an expression with the help of a List. Other wise I have to come up with complex code to analyze the body of the expression and things like that.

Happy coding…

Advertisements

Written by Sony Arouje

February 4, 2014 at 3:19 pm

Posted in .NET

Tagged with ,

Function returns Entity or DTO

with 2 comments

I am working on a project that deals WCF services. In our design we separated Entities and Datacontracts (DTO). The application layer takes care of converting Entities to DTO’s before passing it to Service layer. In the application layer, classes communicates and passes data but I need the inter application layer communication should deals with Entities not DTO’s. So I wanted to find a way so that the function can return Entity or DTO. In this post I will explain how I achieved it, It’s pretty simple.

One option is I could have moved the Entity to DTO mapping to Service layer. I decided not to do it and want to make the service layer light weight.

Another option is shown below.

Let’s take an example of POS system and here we deals with Product. For simplicity I takeout the Interface.

    public class ProductMaintenance
    {
        private Product _currentlyFetchedProduct;

        public ProductMaintenance Get(string productCode)
        {
            //do the logic to fetch product.
            return this;
        }

        public Product ToEntity()
        {
            return _currentlyFetchedProduct;
        }

        public ProductDTO ToDTO()
        {
            //do the logic to map Entity to DTO 
            return new ProductDTO();
        } 
    }

 

The Service class will make a call to the ProductMaintenance as shown below

ProductMaintenance productMaintenance = new ProductMaintenance();
return productMaintenance.GetProduct(productCode).ToDTO();

 

What if the ProductMaintenance class returns more than one type of Data, say it returns Product and List of Product. Then the complexity increases and difficult to handle it.

I introduced a new class to handle this situation called DataGetter, see the code below.

    interface IDataGetter<TSource, TDest>
        where TSource : class
        where TDest : class
    {
        TDest ToDTO();
        TSource ToEntity();
    }

    public class DataGetter<TSource, TDest> : IDataGetter<TSource,TDest>
        where TSource:class
        where TDest:class
    {
        private TSource _entity;
        public DataGetter(TSource entity)
        {
            this._entity = entity;
        }

        public TSource ToEntity()
        {
            return _entity;
        }

        public TDest ToDTO()
        {
            //Do the logic to convert entity to DTO
            return null;
        }
    }

Let’s rewrite the ProductMaintenance class with the new DataGetter.

        public IDataGetter<Product, ProductDTO> GetProduct(string productCode)
        {
            Product productFetched = Repository.GetProduct(productCode);
            return new DataGetter<Product, ProductDTO>(productFetched);
        }

        public IDataGetter<IList<Product>, IList<ProductDTO>> GetAll()
        {
            IList<Product> products = Repository.GetAllProducts();
            return new DataGetter<IList<Product>, IList<ProductDTO>>(products);
        }

The service can call the ProductMaintenance as shown below.

        public ProductDTO GetProduct(string productCode)
        {
            ProductMaintenance productMaintenance = new ProductMaintenance();
            return productMaintenance.GetProduct(productCode).ToDTO();
        }

        public IList<ProductDTO> GetAllProducts()
        {
            ProductMaintenance productMaintenance = new ProductMaintenance();
            return productMaintenance.GetAll().ToDTO();
        }

How to call ProductMaintenance from the same layer, that time we need to deal with Entity instead of DTO. We can easily do that by calling the same function chain with ToEntity() as shown below.

ProductMaintenance productMaintenance = new ProductMaintenance();
return productMaintenance.GetAll().ToEntity();

 

Another advantage of DataGetter is, we can abstract the Entity to DTO mapping from the application class. So any changes to the mapping provider can be done in a single place. For Entity mapping I use AutoMapper.

 

Word of Caution

If we are using any ORM with Lazy loading then make sure the repository session is opened till ToDTO or ToEntity call completes. Say for e.g. if we create the session in GetProduct and close the session in the finally, then ToDTO or ToEntity will throw error as the session is closed and unable to do Lazy loading. I use Castle Windsor to inject the repository dependencies and the session will get closed only in the Dispose function.

Written by Sony Arouje

February 20, 2013 at 8:53 pm

Posted in .NET, WCF

Tagged with ,

%d bloggers like this: