jeudi 28 juillet 2016

How to remove Validation from the service layer

I am trying to create a service layer, however I am unsure how can I decouple my validation from the service, as it doesn't really look DRY for me. I am using ASP.net 4.0 c# with EF.

Here are my layers

BO - Business Object - Share accross all layers
DAL - Data Access Layer
BLL - Business Layer
Service - Service layer

This is one of my business object

    public class Person:Base
    {
        public string FirstName { get; set; }
        public string MiddleName { get; set; }
        public string LastName { get; set; }
        public DateTime DOB { get; set; }
        //public virtual Prefix PrefixID { get; set; }
        public virtual Gender GenderID { get; set; }
        //public virtual Ethnicity EthnicityID { get; set; }
    }

In my DAL folder I have two things, I have PersonDAL, GenderDAL and I have Repository Pattern IGenderRepository, IPersonRepository.

This is how they look

Repository

public interface IPersonRepository : IDisposable
{
    Person PersonID(int id);
    IEnumerable<Person> PersonFN(string _firstname);
    IEnumerable<Person> PersonLN(string _lastname);
    IEnumerable<Person> PersonDOB(DateTime _dob);
    IEnumerable<Person> List();
    void Edit(Person entity);
    void Add(Person entity);
    void Delete(Person entity);
    void Save();
}

public interface IGenderRepository : IDisposable
{
    IEnumerable<Gender> List();
    Gender GenderID(int _id);
    Gender GenderDesc(string desc);
    void Edit(Gender entity);
    void Add(Gender entity);
    void Delete(Gender entity);
    void Save();
}

Data Access Layer

public class PersonDAL : IPersonRepository
{
    private AppContext db;
    public PersonDAL(AppContext _context)
    {
        this.db = _context;
    }

    public IEnumerable<Person> List()
    {
        return db.Person.ToList<Person>();
    }

    public Person PersonID(int id)
    {
        return db.Person.FirstOrDefault((p) => p.ID == id);
    }

    public IEnumerable<Person> PersonFN(string _firstname)
    {
        return db.Person.Where<Person>((p) => p.FirstName == _firstname );
    }

    public IEnumerable<Person> PersonLN(string _lastname)
    {
        return db.Person.Where<Person>((p) => p.LastName == _lastname);
    }

    public IEnumerable<Person> PersonDOB(DateTime _dob)
    {
        return db.Person.Where<Person>((p) => p.DOB == _dob);
    }

    public void Add(Person p)
    {
        db.Person.Add(p);
        Save();
    }

    public void Edit(Person p)
    {
        db.Entry(p).State = EntityState.Modified;
        Save();
    }

    public void Delete(Person p)
    {
        Person _p = db.Person.Find(p.ID);
        db.Person.Remove(_p);
        Save();
    }

    public void Save()
    {
        db.SaveChanges();
    }

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                db.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

public class GenderDAL : IGenderRepository
{
    private AppContext db;

    public GenderDAL(AppContext _context)
    {
        this.db = _context;
    }

    public IEnumerable<Gender> List()
    {
        return db.Gender.ToList();
    }

    public Gender GenderID(int id)
    {
        return db.Gender.FirstOrDefault((g) => g.ID == id);
    }

    public Gender GenderDesc(string desc)
    {
        return db.Gender.FirstOrDefault((g) => g.Description == desc);
    }

    public void Add(Gender g)
    {
        db.Gender.Add(g);
        Save();
    }

    public void Edit(Gender g)
    {
        db.Entry(g).State = EntityState.Modified;
        Save();
    }

    public void Delete(Gender g)
    {
        Gender _g = db.Gender.Find(g.ID);
        db.Gender.Remove(_g);
        Save();
    }

    public void Save()
    {
        try
        {
            db.SaveChanges();
        }
        catch (Exception e)
        {
            Console.Write(e.Message);
        }
    }

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                db.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

}

My business logic still follow the repository pattern

Repository for BLL

public interface IPersonBLL
{
    IEnumerable<Person> List();
    Person ID(int id);
    IEnumerable<Person> FirstName(string _first);
    IEnumerable<Person> LastName(string _last);
    IEnumerable<Person> DOB(DateTime dt);
    Boolean Update(Person p);
    Person Add(Person p);
    Boolean Delete(Person p);
}


public class PersonBLL : IPersonBLL
{
    #region Constant
    private PersonDAL db = null;
    #endregion

    public PersonBLL(AppContext context)
    {
        db = new PersonDAL(context);
    }

    public IEnumerable<Person> List()
    {
        return db.List();
    }

    public Person ID(int id)
    {
        var found = db.PersonID(id);
        if (found == null)
        {
            return null;
        }
        return found;
    }

    public IEnumerable<Person> FirstName(string _first)
    {
        if (_first == null)
        {
            return null;
        }
        return db.PersonFN(_first);
    }

    public IEnumerable<Person> LastName(string _last)
    {
        if (_last == null)
        {
            return null;
        }
        return db.PersonLN(_last);
    }

    public IEnumerable<Person> DOB(DateTime dt)
    {
        if (dt > DateTime.Now )
        {
            return null;
        }

        return db.PersonDOB(dt);
    }

    public Person Add(Person p)
    {
        if (p.FirstName != null)
        {
            if (p.LastName != null)
            {
                p.createdOn = DateTime.Now;
                p.updatedOn = DateTime.Now;
                db.Add(p);
                return p;
            }
        }
        return null;

    }

    public Boolean Update(Person p)
    {
        if (db.PersonID(p.ID) != null)
        {
            p.updatedOn = DateTime.Now;
            db.Edit(p);
            return true;
        }
        return false;
    }

    public Boolean Delete(Person p)
    {
        var found = db.PersonID(p.ID);
        if (found == null)
        {
            return false;
        }
        db.Delete(found);
        return true;
    }

}

To avoid extra text, the gender follow the same concept. Here is my service layer and this is where I am unsure how to proceed

My first question should I have each parameter seperated, or should I wrapped them in an object like Person but not knowing if I can access BO further more. Because it the data may come from the WebAPI or it could come from WPF application.

This is my interface for IPersonService

public interface IPersonService
{
    IEnumerable<Person> FindAllPerson(Person p, string errorMessage);
    Person FindPerson(int id, string errorMessage);
    Person CreatePerson(string first, string mid, string last, DateTime dob, string pref, string gend, string ethnic, string errorMessage);
    Boolean RemovePerson(int id, string errorMessage);
    Boolean UpdatePerson(int id, string first, string mid, string last, DateTime dob, string pref, string gend, string ethnic, string errorMessage);
}

I am not to sure how can I seperate the validation, it just seem not the right place for it.

public class PersonService : IPersonService {

    private PersonBLL _personRep = null;
    private GenderBLL _genderRep = null;
    //private PrefixBLL prefix = null;
    //private AddressBLL address = null;

    public PersonService()
    {
        _personRep = new PersonBLL(new AppContext());
    }

    public Person CreatePerson(string first, string mid, string last, DateTime dob, string pref, string gend, string ethnic, string errorMessage)
    {
        Person p = new Person();
        if (validatePerson(first, mid, last, dob, pref, gend, ethnic, errorMessage))
        {
            p.FirstName = first;
            p.MiddleName = mid;
            p.LastName = last;
            p.DOB = dob;
            Gender g = validateGender(gend, errorMessage);
            p.GenderID = g;
            return _personRep.Add(p);
        }
        return null;
    }

    public Boolean RemovePerson(int id, string errorMessage)
    {
        Person p = _personRep.ID(id);
        if (p == null)
        {
            errorMessage = "Person not found";
            return false;
        }
        else
        {
            return _personRep.Delete(p);
        }
    }

    public Boolean UpdatePerson(int id, string first, string mid, string last, DateTime dob, string pref, string gend, string ethnic, string errorMessage)
    {
        Person p = _personRep.ID(id);
        if (p == null)
        {
            errorMessage = "Person not found";
            return false;
        }
        else
        {
            if (validatePerson(first, mid, last, dob, pref, gend, ethnic, errorMessage))
            {
                if (first != "")
                {
                    p.FirstName = first;
                }

                if (first != "")
                {
                    p.MiddleName = mid;
                }
                if (first != "")
                {
                    p.LastName = last;
                }
                if (first != "")
                {
                    p.DOB = dob;
                }

                Gender g = validateGender(gend, errorMessage);
                if (g != null)
                {
                    p.GenderID = g;
                }
                return _personRep.Update(p);
            }
            return false;
        }

    }

    public IEnumerable<Person> FindAllPerson(Person p, string errorMessage)
    {
        var list = _personRep.List();
        if (list == null)
        {
            errorMessage = "No user found";
            return null;
        }
        return list;
    }

    public Person FindPerson(int id, string errorMessage)
    {
        if (_personRep.ID(id) == null)
        {
            errorMessage = "No ID matches this person";
            return null;
        }
        return _personRep.ID(id);
    }

    protected Boolean validatePerson(string first, string mid, string last, DateTime dob, string pref, string gend, string ethnic, string errorMessage)
    {
        if (first == null)
        {
            errorMessage = "First Name Missing";
            return false;
        }
        return true;
    }

    protected Gender validateGender(string gend, string errorMessage)
    {
        Gender g = _genderRep.GetGenderDesc(gend);
        if (g != null)
        {
            return g;
        }
        errorMessage = "Gender Description Did not match";
        return null;
    }
}

Aucun commentaire:

Enregistrer un commentaire