【问题标题】:Repository and Inheritance存储库和继承
【发布时间】:2012-08-16 22:52:31
【问题描述】:

目前我有一个继承结构,比如说Employee和Manager类,继承自Person抽象类 我应该为每个具体类实现一个存储库还是为整个继承结构实现一个存储库?就我个人而言,我觉得每个具体类都有一个存储库更正确 下面是我对这种方法的实现。我将 Data Mapper 模式与 Repository 一起使用,但在实现这种方法时遇到了一些困难:除了 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类中,按理说应该放在repository类中,但是一般repository类中,EmployeeNo这个子类的具体属性我们不知道类和Manager类中的ManagerNo,因此我们无法在存储库中创建通用的SqlCommand

有没有更好的方法? 非常感谢

【问题讨论】:

  • 看起来你真的在用映射器类重新发明轮子并滚动你自己的 ORM。

标签: c# inheritance repository datamapper


【解决方案1】:

有没有更好的方法?非常感谢

是的,有更好的方法。

当您使用 SQL 数据库时,请避免重新发明轮子,而是使用 ORM 工具,例如 nHibernateEntity Framework,最好使用 LINQ 支持。

【讨论】:

  • 您好,谢谢您的建议,但是由于我公司的限制,我们不能使用实体框架或nhibernate,所以我需要手动构建一个
猜你喜欢
  • 1970-01-01
  • 2011-09-15
  • 1970-01-01
  • 1970-01-01
  • 2011-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-28
相关资源
最近更新 更多