2011年12月31日 09:44 "@hushawn"的内容
我在创建对象时候,用一个参数来确定是否延迟加载是否可以?

另外,聚合内的非聚合根子对象是否可以延迟加载???

另外,能否同时有引用ID和引用对象,因为,我要去延迟加载的时候,如果没ID,就不知道要加载哪个对象了??? ...

这些都是实现手段优雅完美与否了。

可以使用CategoryLazyLoader等委托方式调用;聚合内子对象当然可以延长加载,而且是由聚合根对象来实现。

创建对象时,不需要用参数来标识是否延迟加载吧?只要判断对象是否为空就可以了,比如category是否为空等,至于category的ID如CategoryID当然在父对象Article中不需要了,因为你可以根据ArticleID到数据表中获得其外键关联字段CategoryID,然后加载其category即可。

非常感谢,另外如果用委托,那一个领域对象里,可能会有很多委托,而且从Repository里获取对象后,还要注册一个委托方法,注册方法这个动作,放在那里弄比较合适,如应用服务层,或领域服务里??

创建对象时,不需要用参数来标识是否延迟加载吧?
我的意思,开始加载根对象前,就决定本次加载是否是延迟加载

[该贴被hushawn于2011-12-31 11:30修改过]
[该贴被hushawn于2011-12-31 11:35修改过]

2011年12月31日 11:25 "@hushawn"的内容
从Repository里获取对象后,还要注册一个委托方法,注册方法这个动作,放在那里弄比较合适,如应用服务层,或领域服务里??

我的意思,开始加载根对象前,就决定本次加载是否是延迟加载 ...

委托方法注册放在聚合根对象的工厂中,因为工厂负责创建。

是否需要参加决定延迟加载,在你设计代码时已经决定了,比如比较小的聚合对象群就一次加载,比较大的就延迟加载。

尽量一次加载,采取延迟加载是因为技术条件限制,比如内存不够大等原因,但是如果采取分布式内存系统如NoSQL或Neo4j就没有这个限制了。

我能这样理解吗??用户是一个单独的领域模型,角色也一样。通过给用户分配角色的事件,使得两个领域模型有了联系。而不一样把用户和角色归为到一个领域模型中是吗?我也刚开始看这些东西不知道理解是否正确!

我记得工厂是新创建一个对象去持久化,而现在应该是仓储(Repository)里获取后加载对象去进行操作,这个时候也用工厂??而且现在注册的方法应该是另外一个仓储(Repository)的方法,如
IEmployeeRepository employeeRepository;
user.EmployeeLazyLoader = employeeRepository.FindByUserId;
因为仓储是领域对象仓库,要获取对象都要到对应的仓储里去获取,这么理解对吗?还有就是工厂里可以有仓储接口吗?
是不是我在工厂里创建两种对象创建方法,一种是数据从界面那边新生成的新对象创建,一种通过仓储从持久化介质读取后加载,他们两个是在对象生命周期的不同阶段????

而刚才我本来想这么弄
public class UserService
{
private IEmployeeRepository employeeRepository;
private IUserRepository userRepository;

public UserService(IEmployeeRepository employeeRepository)
{
this.employeeRepository = employeeRepository;
}

public void Register(User user)
{
user.EmployeeLazyLoader = employeeRepository.FindByUserId;
}
}
把它放在领域对象User对应的领域服务里去做,如上,这里不是ApplicationService(供界面调用)?这样做合理吗

另外如果不是延迟加载,可能会拉出对象树,对,刚才您说了,根据实际情况进行代码设计

又想到一个问题,我觉得仓储里加载的内容是一个聚合的内容,所以对关联的对象的加载应该是延迟加载,对聚合内的所有内容是一次性加载

又想到个问题,用户和角色之间应该就是多对多关系,而且定义成用户到角色的单向关联,用户和员工间一般是一对一,跟员工相比,用户只是可以指定多个角色,而用户只可以指定一个员工,用户和角色,用户和员工间的关系类别是一致的,只是简单的关联,而没有我标题上说的什么用户角色类,还有什么聚合....

又想到了个问题,一个聚合边界内可以一次性加载,我理解的聚合边界里面可能有多个聚合根,相对来说关联程度比较紧密,一个聚合根的所有直接关联,间接关联的都当作聚合边界之外,聚合边界之间可以延迟加载,所以尽量减少关联,我是这么理解的...老师在吗??



[该贴被hushawn于2011-12-31 17:29修改过]

前面我想你已经明白我的意思,需要对象创建的地方都需要工厂。我们前面讨论的是聚合的懒加载问题,而一个业务是否是聚合还需要讨论,我不同意将用户和角色看成聚合,前面说得很清楚,看看其他人怎么回答吧,祝新年快乐

很久没来了,jdon样式变得不错,现在我来当当“其他人”吧。

入题:你所说的角色到底是指参与事件的“参与者”,还是指用户组策略的权限系统中的“用户组”。若果是后者,那么“(3)因为一般只会关心用户有哪些角色,而不会关心一个角色有哪些用户使用,所以角色里没有用户列表和角色分配类列表;”这句话依据不足,而且在用户权限系统方面,没有什么是一定的,是以用户组策略,还是功能权限分配,还是其他完全取决你自己。

而“(5)另外我如果要在用户和一个员工关联,也就是把这个用户指定给了一个员工……”这个理解,与前者理解是相关的。我就我一方的观点解析一下你的第五点:

我以前曾发过帖子,参与者与驱动者的区别,这是真正理解用户登录认证系统和领域逻辑的划分。

驱动者在用户登录认证系统中,包含着功能权限控制等。参与者则是在逻辑领域中,是纯净的逻辑部分,有没有登录认证,权限限制都不会影响领域逻辑。按你的例子,用户是驱动者,员工是参与者,用户驱动着领域,它是领域事件发出者,是领域外部的存在,要用一个比喻的话,用户就好像多米诺骨牌中选择推第一个骨牌的手,而员工只是骨牌的一部分。若果用户是导演,员工则是演员。

鉴于这样的理解,我认为用户和员工没有任何直接的联系,是两个独立的部分。所以在简单的以关系数据库为基础的系统,完全可以跳过Repository,以基础设施为切入验证。

这是我的个人观点——“天地不仁,以万物为刍狗”。

但是业务上要给员工指定一个用户登录系统,他们之间起码有个关联关系吧?

我说的用户和角色是权限管理的一部分,可以把多个角色指定给一个用户,可以把多个功能指定一个角色

我想问下
有没办法动态指定某次查询的关联对象是否是延迟加载,就是对同一Repository里的同一个查询方法,在不同时候指定是或否延迟加载,如FindById(id),有时候只需要单单用户数据,有时候需要用户及其相关联的员工及相关联角色对象数据,还是直接就2种情况各自写个方法?

另外,从界面上获取数据创建新的领域对象最后持久化,以及从持久化介质加载领域对象是否都要用工厂,那不是有太多工厂类,工厂类应该是属于领域层吧,工厂类里可以访问Repository接口吗?而且我是用datarow里获取数据装载领域对象,涉及到数据库字段??


[该贴被hushawn于2012-01-05 11:51修改过]

纠结死了,最后还是决定,在领域模型中同时加入ID(取个其他名字,比如EmployeeEntityKey)和引用关联,要不很多功能都实现不了,而且影响性能

public class User
{

public string UserAccount { get; set; }
public int EmployeeEntityKey { get; set; }
public virtual Employee Enployee { get; set; }
}

如果不这样,从界面保存数据的时候,employeeId无法传递,只能通过Employee关联对象来保存截面的employeeId,持久化的时候,又要从该Employee取出employeeId;另外,从仓储取出对象的时候,想延迟加载的时候,也不能记录,要加载的员工ID,这里当然可以通过用户得到,但有时候多对多的时候,无法获取,无法实现延迟加载.....
大家觉得这样可行吗??

不太好吧, 有潜在的一致性问题, 关联改变时, 你要同时修改ID和对象引用.

于是问banq老师, 一定要避免用ID来引用其他对象吗. 用ID来代替对象引用行不行?

------------
@hushawn 感觉你的思路完全在DDD上了, 应该从需求出发吧...
[该贴被sorra于2012-01-12 15:23修改过]
[该贴被sorra于2012-01-12 15:39修改过]
[该贴被sorra于2012-01-12 15:48修改过]
------------
顺便报BUG, 点击编辑, 但没有提交, 仍然会显示"该贴被...修改过"
[该贴被sorra于2012-01-12 15:49修改过]

我也在你这个问题上纠集,很多观点都告诉,聚合根之间应该用ID来引用,这样避免了聚合根之间持久化的影响。但如果不走CQRS这样的模式,用经典的DDD我又不知道如何去做一些查询操作。希望你有了解决方案,能告诉我下。你的引用方式我在使用EF4.1的时候出现了一些问题,聚合与聚合之间的对象引用是会出问题的。

这期间阅读了Martin Fowler的PoEAA<企业应用架构模式>中的"延迟加载"一节.
想到几点建议
1. 既然是用.NET, 而且是用Entity Framework, 持久层设计上就要受框架的限制. 建议避免过度设计.
2. 要延迟加载, 可以用代理模式. 比如, UserProxy, EmployeeProxy等, 把引用, ID之类的问题封装在这里. 这样聚合根就可以只使用对象引用了.


[该贴被sorra于2012-02-16 13:36修改过]