实体框架 – DDD,实体框架,聚合实体行为(Person.AddEmail等)
这里是一个简单的例子,我正在运行的问题不在于这里提供的一些想法和其他关于DDD的地方.
说我有一个ASP.NET MVC 3网站创建/操纵一个人.控制器访问应用程序服务层(PersonService),后者又使用域实体(EF 4 POCO)和PersonRepository进行更改并持久化.为了简单起见,我在这里省略了所有的界面.在这种情况下,人是根,为了简单起见,只有电子邮件地址(也假定电子邮件不是不可变的,可以更新). 选项1: // Person Service public class PersonService { // constructor injection to get unit of work and person repository... // ...methods to add/update a person public EmailAddress AddEmailAddress(int personId,EmailAddress email) { Person p = personRepository.Find(p => p.Id == personId).First(); p.AddEmail(email); uow.SaveChanges(); return email; } public EmailAddress ChangeEmailAddress(EmailAddress email) { Person p = personRepository.Find(p => p.Id == personId).First(); p.ChangeEmail(email); // change state of email object here so it's updated in the next line??? // if not here,wouldn't the Person entity have to know about the context // or use a service? uow.SaveChanges(); return email; } } // Person Repository public class PersonRepository { // generic repository implementation } // Person Entity public class Person { public string Name { get;set; } public IEnumerable<EmailAddress> EmailAddresses { get;set; } public void AddEmail(EmailAddress email) { this.EmailAddresses.Add(email); } public void ChangeEmail(EmailAddress email) { EmailAddress orig = this.EmailAddresses.First(e => e.Id == email.id); // update properties on orig // NOW WHAT? [this] knows nothing about the context in order to change state,etc,or do anything to mark the email add updated } } // Email public class EmailAddress { public string Email { get;set; } public bool IsPrimary { get;set; } } 选项二: // Person Service public class PersonService { // constructor injection to get unit of work and person repository... // ...methods to add/update a person public EmailAddress AddEmailAddress(int personId,EmailAddress email) { Person p = personRepository.Find(p => p.Id == personId).First(); personRepository.AddEmail(personId,email); uow.SaveChanges(); return email; } public EmailAddress ChangeEmailAddress(EmailAddress email) { personRepository.ChangeEmail(email); uow.SaveChanges(); return email; } } // Person Repository public class PersonRepository { // generic repository implementation } // Person Entity public class Person { public string Name { get;set; } public IEnumerable<EmailAddress> EmailAddresses { get;set; } } // Email public class EmailAddress { public string Email { get;set; } public bool IsPrimary { get;set; } } 无论如何,有什么想法吗? 谢谢Brian
选项1是要走的路.
推理是简单的 – 更改电子邮件地址是领域关注.我敢打赌你的域名专家说他们将需要更改电子邮件.自动将电子邮件更改的逻辑标记为应该在域模型中生活的业务逻辑.对象主要由他们的行为定义,而不是他们所持有的数据. 另外 – 在您选择使用工作单位之前,先考虑一下,并将所有服务都包装起来.总结根应该是绘制事务边界,如果服务器只包含存储库和域对象调用,服务通常是无用的. 我会有这样的事情: public class Person{ public Email Email{get;private set;} public void SpecifyEmail(Email email){ //some validation,if necessary EnsureEmailCanBeChanged(); //applying state changes Email=email; //raising event,if necessary Raise(new EmailChanged(this)); } public class EmailChanged:Event<Person>{ public EmailChanged(Person p):base(p){} } } public class Email{ public Email(string email){ //validations (e.g. email format) Value=email; } //implicit to string,explicit from string conversions } public class PersonController{ public ActionResult SpecifyEmail(int person,string email){ _persons.Get(person).SpecifyEmail((Email)email); return RedirectToAction("Person",new{person}); } } 我正在使用NHibernate – 它足够聪明,以确定自从上次持续存在以来发生了什么变化.很难说实体框架如何处理这个. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- ruby-on-rails – 如何防止垃圾邮件中的垃圾邮件
- 7月18日 杭州 OSC 源创会开始报名 —— Swift 2.
- ios – fastlane工具和xcode8,我还应该使用吗?
- 我的Cocos2d-x学习笔记(二十二)CCTextFieldTTF
- react.js 翻页插件
- 小酌 Swift 2.0 - #available 语法处理 iOS 多版
- c – OpenCV DescriptorMatcher radiusMatch和kn
- [xml] <![CDATA[ ]]>是什么意思?
- C#如何用另一个字符串的部分替换一个字符串的部分
- SSRS 2012 聚合函数 -- 隔行换色示例