Репозиторий и наследование

В настоящее время у меня есть структура наследования, скажем, класс Employee и Manager, наследуемый от абстрактного класса Person. Должен ли я реализовать один репозиторий для каждого конкретного класса или один репозиторий для всей структуры наследования? Лично я считаю более правильным один репозиторий для каждого конкретного класса. Ниже приведена моя реализация этого подхода. Я использую шаблон Data Mapper вместе с репозиторием, но у меня есть некоторые трудности при реализации этого подхода: некоторые методы я не знаю, куда поместить, кроме класса Data Mapper, но очень неудобно помещать туда также

public enum PersonType
{
    Unknown = 0,
    Employee = 1,
    Manager = 2
}

public abstract class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }    
    public PersonType Type { get; set; }

    //Omitted properties and methods
}

public class Employee : Person
{
    public string EmployeeNo { get; set; }

    //Omitted properties and methods
}

public class Manager : Person
{
    public string ManagerNo { get; set; }

    //Omitted properties and methods
}

Ниже приведены классы картографов:

public interface IMapper
{
    bool CanMap(PersonType type);
    Person MapFrom(DataRow dataRow);

    //This method is awkward to put here
    SqlCommand CreateUpdateCommandFrom(Person person);  
}

public abstract class MapperBase : IMapper
{
    public abstract bool CanMap(PersonType type);
    public abstract Person MapFrom(DataRow dataRow);
    public abstract SqlCommand CreateUpdateCommandFrom(Person person);

    protected T MapCommonPropertiesFrom<T>(DataRow dataRow) where T : Person, new()
    {
        return new T
        {
            //Populate common properties like id, name, age
        };
    }
}

public class EmployeeMapper : MapperBase
{
    public override bool CanMap(PersonType type)
    {
        return type == PersonType.Employee;
    }

    public override Person MapFrom(DataRow dataRow)
    {
        Employee employee = MapCommonPropertiesFrom<Employee>(dataRow);
        //Populate employee properties
        return employee;
    }

    public override SqlCommand CreateUpdateCommandFrom(Person person)
    {
        SqlCommand updateCmd = new SqlCommand();
        //Set parameters for updateCmd from person properties
        return updateCmd;
    }
}

//Similar class for ManagerMapper

Ниже приведен класс регистрации для поиска класса картографа.

public static class MapperRegistry
{
    private static List<IMapper> _Mappers = RegisterMappers();

    private static List<IMapper> RegisterMappers()
    {
        return new List<IMapper>
        {
            new EmployeeMapper()
            //ManagerMapper
        };
    }

    public static IMapper FindMapperFor(PersonType type)
    {
        foreach (IMapper eachMapper in _Mappers)
        {
            if (eachMapper.CanMap(type))
            {
                return eachMapper;
            }
        }

        throw new ArgumentException(string.Format("Cannot find mapper for {0}", type));
    }
}

И последний класс - это класс репозитория

public class PersonRepository
{   
    public Person FindBy(int id)
    {
        //Execute query command in db, get datatable back, store each person
        DataTable returnedData = ExecuteQueryCommand(id);
        PersonType type = int.Parse(returnedData.Rows[0], "Id");
        IMapper mapper = MapperRegistry.FindMapperFor(type);
        return mapper.MapFrom(returnedData.Rows[0]);
    }

    private DataTable ExecuteQueryCommand(int id)
    {
        //Execute query command in db
        return new DataTable();
    }

    public void Update<T>(T person) where T : Person
    {
        IMapper mapper = MapperRegistry.FindMapperFor(person.Type);
        SqlCommand updateCmd = mapper.CreateUpdateCommandFrom(person);
        //Execute update command
    }
}

Я считаю неправильным то, что CreateUpdateCommandFrom(), в настоящее время помещенный в класс Mapper, по праву должен быть помещен в класс репозитория, но в общем классе репозитория мы не знаем конкретных свойств дочернего класса, таких как EmployeeNo в классе Employee и ManagerNo в классе Manager, поэтому мы не можем создать общий SqlCommand в репозитории

Есть ли лучший подход? Большое спасибо


person Phuong Nguyen    schedule 21.08.2012    source источник
comment
Похоже, вы действительно заново изобретаете колесо с классами картографов и запускаете свой собственный ORM.   -  person ElvisLives    schedule 21.08.2012


Ответы (1)


Есть ли лучший подход? Большое спасибо

Да, есть лучший подход.

Поскольку вы используете базу данных SQL, не изобретайте велосипед и используйте инструмент ORM, такой как < href="http://nhforge.org" rel="nofollow">nHibernate или Entity Framework, желательно с поддержкой LINQ.

person Zaid Masud    schedule 21.08.2012
comment
Привет, спасибо за ваше предложение, но из-за ограничений в моей компании мы не можем использовать инфраструктуру сущностей или nhibernate, поэтому мне нужно создать ее вручную. - person Phuong Nguyen; 21.08.2012