在POCO验证的ASP.NET MVC /实体框架的建议 [英] Advice on POCO Validation with ASP.NET MVC/Entity Framework

查看:166
本文介绍了在POCO验证的ASP.NET MVC /实体框架的建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的情况:


  • ASP.NET MVC2 Web应用程序

  • 实体框架4(纯POCO的,自定义数据上下文)

  • Repository模式

  • 工作模式的单位

  • 依赖关系注入

  • 服务层中介控制器 - >库

所以基本上,所有的很酷的东西。 :)

事件流为基础的UI操作(添加邮报):


  1. 控制器调用的添加(邮政)在服务层的方法

  2. 服务层调用添加(T)上库

  3. 库调用自定义数据上下文ADDOBJECT(T)

  4. 控制器调用提交()在工作单位

现在,我试图找出在那里我可以把我的验证。

在这个阶段,我需要验证的两种类型:


  1. 简单,独立的POCO验证,如后必须有一个标题。这似乎是一个天作之合数据注释在POCO的的。

  2. 复杂的业务验证,如不能添加到锁定张贴评论。这不能由数据注释来完成。

现在,我一直在读编程实体框架,第二版朱莉·勒曼(这是BTW优秀),并已寻找到钩住的 SavingChanges 以执行事件最后一分钟的验证。这将是确保验证的好办法总是发生每当我做东西(添加,修改,删除),但它也是一个有点晚IMO(作为项目已经在状态管理器) - 如果验证失败,我能做些还等什么,删除它们。

我当然可以让我的POCO的实现一个接口(比如IValidatable),而这个事件中调用该接口上的一个方法。

但这似乎亡羊补牢为经营验证 - 这是共识

我基本上找的指导在这里,我试图设计复​​杂的业务逻辑的可重复使用的,智能验证方案,给我的上述架构。

另一条曲线球为您服务 - 如你所知,POCO与EF意味着POCO的对数据库的所有属性 - 所以我可能有一个帖子ID属性,具有get / set访问(如EF需要得到/设置这些属性)。

但问题是,帖子ID是一个身份列,因此如何保护领域被明确地设置?例如,如果我(因为某些原因),请执行以下操作:

  VAR后= service.FindSingle(10);
post.PostId = 10;
unitOfWork.Commit();

这将抛出SQLException。我怎样才能prevent呢?我不能隐藏属性(让它私有,甚至内部)作为POCO的是在一个单独的组件安装到存储库。

在验证的注意事项 - 我打算创建(从Exception派生)自定义异常。因此,当验证失败,我需要把这些异常。

这样的话,我可以code这样的事情我控制器上:

  [HttpPost]
公众的ActionResult AddPost(后后)
{
   尝试
   {
      IUnitOfWork UOW =新的UnitOfWork();
      postService.Add(岗位);
      uow.Commit();
   }
   赶上(InvalidPostOperation IPO)
   {
      //将错误视图模型
   }
}

我将不得不手工做服务层每次我做一个添加验证?那我该怎么处理保存? (因为这是工作,而不是服务层的单元)。

所以要prevent这从一个所有的地方的问题,这里是我的问题:


  1. 简单POCO验证 - 这应该与数据注释做了什么?优点/缺点/陷阱?

  2. 在什么情况下(如果有的话)我们应该挂钩到在 SavingChanges ,以提供验证EF数据上下文的事件?

  3. 我应该在哪里表演复杂的业务验证?在服务的明确地,或在方法POCO的(我可以从服务调用)。如何创建一个智能/可重复使用的方案?

  4. 我们怎样才能不被篡改隐藏POCO的自动生成的属性?

任何想法,将AP最多preciated。

很抱歉,如果这个职位是太长,但它是一个重要的问题,一个可以用很多方式来解决,所以我想提供,以便尽可能最好的回答所有的信息。

感谢。

修改

下面的答案是有帮助的,但我还是比较理想的状况寻找更多的想法。其他人?


解决方案

  1. 好了就像你说的, DataAnnotations 不适合于所有情况。缺点主要是复杂的验证(多个属性和多个属性不同的对象),在我的经验。

  2. 如果我是你,我会离开企业/域验证了数据层(EF)尽可能的。如果有一个数据层验证的情况下,再细。(例如验证复杂的父/子关系 - 这纯粹是DB的东西)

  3. 是的,复杂的业务验证应在服务层或模型中的对象(连接,通过局部类或某些继承方法:接口/派生类)。有这个ActiveRecord的人,Repository模式人与DDD人与人之间的辩论,但对你的作品去了,很简单,将使快速部署和低成本的应用维护。这是一个简单的<一个href=\"http://stackoverflow.com/questions/1721327/validate-object-based-on-external-factors-ie-data-store-uniqueness/1741831#1741831\">example为域对象但仍与 DataAnnotations 接口兼容,因此您可以如何连接更复杂的验证是MVC友好。

  4. 问得好。 - 酮我还没有找到一个解决方案我很高兴又100%。我打私人制定者的想法,这是不是很大。有此总结埃文斯DDD书的快速阅读。这是伟大的快速阅读,它可能会提供有关模型对象和值对象的用途和不同的一些见解。这就是我认为的对象设计将减轻与财产篡改(如你所说),但没有固定的属性显示你有问题。也就是说,另一种解决方案可能会在其他地方。希望这有助于。

Here's the scenario:

  • ASP.NET MVC2 Web Application
  • Entity Framework 4 (Pure POCO's, Custom Data Context)
  • Repository Pattern
  • Unit of Work Pattern
  • Dependency Injection
  • Service Layer mediating Controller -> Repository

So basically, all the cool stuff. :)

Flow of events for a basic UI operation ("Adding a Post"):

  1. Controller calls Add(Post) method on service layer
  2. Service layer calls Add(T) on repository
  3. Repository calls AddObject(T) on custom data context
  4. Controller calls Commit() on Unit of Work

Now, i'm trying to work out where i can put my validation.

At this stage, i need two types of validation:

  1. Simple, independant POCO validation such as "post must have a title". This seems a natural fit for Data Annotations on the POCO's.
  2. Complex business validation, such as "cannot add a comment to a locked post". This can't be done by Data Annotations.

Now, i have been reading "Programming Entity Framework, Second Edition" by Julie Lerman (which is excellent BTW), and have been looking into hooking into the SavingChanges event in order to perform "last-minute" validation. This would be a nice way to ensure validation always happens whenever i do "something" (add, modify, delete), but it's also a little late IMO (as the items are already in the state manager) - so what can i do if validation fails, remove them?

I could of course make my POCO's implement an interface (say "IValidatable"), and call a method on this interface during this event.

But this seems "too late" for business validation - is this the consensus?

I'm basically looking for guidance here, i'm trying to design a re-usable, intelligent validation scheme for complex business logic, given my above architecture.

Another curve-ball for you - as you know, POCO's with EF mean the POCO's have all the properties on the DB - so i might have a "PostID" property, with get/set accessors (as EF needs to get/set these properties).

But the problem is, "PostID" is an identity column, so how do i protect the field from being explicity set? E.g if i (for some reason) do the following:

var post = service.FindSingle(10);
post.PostId = 10;
unitOfWork.Commit();

This will throw a SqlException. How can i prevent this? I can't "hide" the property (make it private, or even internal) as the POCO's are in a seperate assembly to the Repository.

A note on validation - i'm planning to create custom exceptions (deriving from Exception). So when validation fails, i need to throw these exceptions.

That way, i can code something like this on my controller:

[HttpPost]
public ActionResult AddPost(Post post)
{
   try
   {
      IUnitOfWork uow = new UnitOfWork();
      postService.Add(post);
      uow.Commit();
   }
   catch(InvalidPostOperation ipo)
   {
      // add error to viewmodel
   }
}

Will i have to manually do validation on the service layer everytime i do an Add? Then how can i handle Save? (as this is on the Unit of Work, not the service layer).

So to prevent this from being a "all over the place" question, here are my questions:

  1. Simple POCO validation - should this be done with Data Annotations? Pros/cons/gotchas?
  2. Under what circumstances (if any) should we be hooking into the SavingChanges event of the EF Data Context in order to provide validation?
  3. Where should i be performing complex business validation? In the service explicity, or a method on the POCO's (which i can call from service). How can i create an intelligent/reusable scheme?
  4. How can we "hide" auto-generated properties of POCO's from being tampering with?

Any thoughts would be most appreciated.

Apologize if this post is "too long", but it's an important issue and one that can be solved in many ways, so i wanted to provide all the info in order for the best possible answer.

Thanks.

EDIT

The below answer is helpful, but i'm still (ideally) looking for more thoughts. Anyone else?

解决方案

  1. Well like you said, DataAnnotations is not appropriate for all situations. Cons are mainly complex validation (multiple property and multiple property different object) in my experience.
  2. If i were you, i would leave business/domain validation out of the Data Layer (EF) as much as possible. If there is a Data Layer validation scenario, then fine (eg. validating complex parent/child relationships - this is purely DB stuff).
  3. Yes, the complex business validation should be in the Service Layer or in the Model Objects (attached, via partial classes or some inheritance approach: interfaces/derived classes). There's debate about this between ActiveRecord people, Repository Pattern people and DDD people, but go with what works for you, is simple and will enable rapid deployment and low cost application maintenance. This is a simple example of how you might attach more complex validation to domain objects yet is still compatible with the DataAnnotations interface and thus is 'MVC friendly'.
  4. Good question. -one i have not found a solution i'm 100% happy with yet. I have played with the idea of private setters and it's not great. Have a quick read of this summarized Evans DDD book. It's great quick read and it might provide some insight about the purpose and difference between Model Objects and Value Objects. This is where i think object design will mitigate the problems your having with the property "tampering" (as you call it) but without fixing the property visibility. Ie, another solution might lie elsewhere. Hope this helps.

这篇关于在POCO验证的ASP.NET MVC /实体框架的建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆