2009-01-22 33 views
8

我目前正在重写应用程序以使用完全从域图层抽象数据库的数据映射器。不过,我现在想知道这是处理领域对象之间的关系,更好的办法:直接域对象 使域对象意识到数据访问层是否不正确?

  • 写的关系逻辑入内从相关数据映射器

    1. 呼叫必要find()方法本地数据映射器(这是PoEAA中的例子),然后调用域对象内的本地数据映射器函数。

    要么在我看来,为了保留“胖模型,瘦身控制器”的口头禅,域对象必须知道数据映射器(无论是他们自己还是他们有权访问系统中的其他映射器)。此外,选项2似乎不必要地使数据访问层复杂化,因为它在多个数据映射器上创建表访问逻辑,而不是将其限制为单个数据映射器。

    那么,是不是不正确,使域对象了解相关数据映射器,并直接从域对象调用数据映射的功能呢?

    更新:这些是我可以设想处理域对象之间关系问题的唯一两种解决方案。任何显示更好方法的例子都会受到欢迎。

  • 回答

    7

    恐怕你已经稍微误解Repository模式的意图。

    资源库是为了表现得像一个内存中收集特定的域对象,通常是一个聚合根:

    interface EmployeeRepository 
    { 
        List<Employee> retrieveBy(Criteria someCriteria); 
        void store(Employee someEmployee); 
        int countOf(Criteria someCriteria); 
        // convenience methods 
        Employee retrieveById(String id); 
        Employee retrieveBySSN(String ssn); 
    } 
    

    这个代码的客户不知道该集合是否是在内存中,像你必须进行单元测试,或者在某些情况下与ORM映射器交谈,或在其他情况下调用存储过程,或者维护某些域对象的缓存。

    这仍然不能回答你的问题。实际上,您可能有域对象具有委托给正确存储库的save()和load()方法。我不认为这是一条正确的路,因为持久性几乎不是业务领域的一部分,并且它给你的域对象提供了不止一个改变的理由。

    查看this related question以获得更多漫游。

    在回应这个答案一些意见:

    有效的批评。但是,我仍然 困惑,然后在如何获得一个单一的 域对象或一个 相关域对象的集合时,在一个现有的域对象的 上下文中。 - gabriel1836

    假设员工有很多技能。我认为没有错与员工库调用技能库这样的:

    // assume EmployeeRepository talks to a DB via sprocs 
    public Employee retrieveById(String id) 
    { 
        ResultSet employeeResultSet = this.database.callSproc("PROC_GetEmployeeById", 
         new Object[] { id }); 
    
        List<Skill> skills = 
         new SkillRepository().retrieveBy(new EqualsCriteria("EmployeeId", id)); 
    
        Employee reconstructed = new EmployeeFactory().createNew(). 
                fromResultSet(employeeResultSet). 
                withSkills(skills). 
                build(); 
    
        return reconstructed;  
    } 
    

    另一条路线是而不是调用的技能库,有员工储备库调用,在这个例子中,存储过程加载结果集技能,然后委托技能工厂获取技能列表。

    我不能让到存储库 通话以及是否发出调用 数据映射器或加载在内存中的对象 是其关注的,不是吗? - gabriel1836

    没错。我通常以这种方式在单元测试中嘲笑整个数据层。

    7

    是的。问问你自己为什么域对象知道这样的事情?甚至不是为什么,但如何?你要将你的DAL注入你的Domain对象?

    您应该遵循SRP只是住一切。当你遍历你的域时,你应该不知道这些属性是通过延迟加载填充还是从实例化中提取。

    我已经写在他们有DAL对象域模型,这是保持一个噩梦。然后我学习了NHibernate,我的域由POCO's和他们各自想要封装的业务逻辑组成。

    [编辑]

    下面是更多信息。如果我试图解释它,我只会让自己难堪。我只能说作为用户的实现。这里有一篇关于Domain Model management的文章。你感兴趣的是拦截器和mixin的实现。

    public class Employee 
    { 
        public Employee() 
        { 
         Skills = new List<Skill>(); 
        } 
    
        public string Name { get; set; } 
        public IList<Skill> Skills { get; private set; } 
    
        public void AddSkill(Skill skill) 
        { 
         // Perform Domain specific validation here... 
    
         Skills.Add(skill); 
        } 
    } 
    

    正如你所看到的,我的数据访问需求不上我的网域设计强加责任:

    有了这些工具,你可以写成如下雇员类。

    +0

    你能否提供一个例子来说明如何处理在现有的域对象中加载其他域对象?例如,如何为员工加载技能集合? – 2009-01-22 04:28:40

    +0

    您希望存储库对象执行此操作...领域模型应该是坚持不懈的,但是应该有另外一个知道持久性的对象。 – Webjedi 2009-01-22 04:46:50

    0

    已经做了一些进一步的阅读和寻找合适的模式后,我偶然发现the Repository Pattern

    从我所看到的,这恰恰是设想的解决方案,允许领域类人,以正确的分配,查询到相应的数据映射,同时保留域对象和数据映射完全抽象。

    0

    我不同意,我认为域对象可以通过抽象工厂访问存储库。

    public class Client 
    { 
        public void ChangeZipCode(string zipCode) 
        { 
        // This method access memory or database depending on the factory context 
        bool zipCodeExists = RepositoryFactory.Get<IZipCode>().Exists(zipCode); 
        this.zipCode = zipCode; 
        } 
    } 
    

    通过使用这种模式,它没有必要在你的代码 但只有仓库工厂注入库接口。

    public abstract class RepositoryFactory 
    { 
        // Class operations 
        private static _globalInstance; 
        public static CreateGlobalInstance(RepositoryFactory factory) 
        { 
        _glocalInstance = factory; 
        } 
        public static I Get<I>() 
        { 
        return _globalInstance.Get<I>(); 
        } 
        ///////////////////// 
    
        ///// this operation should be inherited by: 
        ///// * NHibernateRepositoryFactory // 
        ///// * Linq2SqlRepositoryFactory //// 
        ///// * NUnitRepositoryFactory ///////  
        ///// it depends in your context //////////////////////// 
        public abstract I GetRepository<I>(); 
    } 
    

    我在单元测试中没有任何问题,一直这样做。

    因此只有在这个类RepositoryFactory中需要依赖注入。

    相关问题