关于使用ASP.NET MVC /实体框架进行POCO验证的建议 [英] Advice on POCO Validation with ASP.NET MVC/Entity Framework

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

问题描述

下面是这种情况:


  • ASP.NET MVC2 Web应用程序

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

  • 存储库模式

  • 工作单元格

  • 依赖注入

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

  • 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. :)

基本UI操作的事件流程(添加帖子):

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


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

  2. 服务层调用添加(T) / li>
  3. 存储库调用 AddObject(T)在自定义数据上下文

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

  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. 简单,独立的POCO验证如post必须有标题。这似乎适合数据注释在POCO上。

  2. 复杂的业务验证,例如无法向锁定的帖子添加评论。数据注释无法完成。

  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.

现在,我一直在阅读Julie Lerman(这是很好的BTW)的编程实体框架,第二版,并已经查看 SavingChanges 事件,以执行最后一分钟验证。这将是一个很好的方法,以确保验证始终发生每当我做某事(添加,修改,删除),但它也有一点晚IMO(因为项目已经在状态管理器) - 如果验证失败,我可以做什么,删除它们?

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?

我当然可以让我的POCO实现一个界面(比如说IValidatable),并调用一个方法这个接口在这个事件中。

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.

对于你来说,另一个曲棍球 - 你知道,POCO的EF意味着POCO拥有数据库中的所有属性 - 所以我可能会有一个PostID属性,带有get / set访问器(作为EF需要获取/设置这些属性)。

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).

但问题是,PostID是一个 identity 列,那么我如何保护字段不被显式设置?如果我(由于某种原因)执行以下操作:

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();

这将抛出一个SqlException。我如何防止这种情况?我不能隐藏属性(使其为私有的,甚至是内部的),因为POCO是在Repository的一个单独的程序集中。

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.

有关验证的注释 - 我打算创建自定义异常(派生自Exception)。所以当验证失败时,我需要抛出这些异常。

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
   }
}

每次我做一个添加,我必须手动对服务层进行验证吗?那我该怎么处理Save? (因为这是在工作单位,而不是服务层)。

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. 简单的POCO验证 - 应该用Data Annotations完成吗?优点/缺点/难点?

  2. 在什么情况下(如果有的话)应该挂在EF Data Context的 SavingChanges 事件中以提供验证?

  3. 我应该在哪里进行复杂的业务验证?在服务显性中,或POCO上的方法(我可以从服务中呼叫)。如何创建一个智能/可重复使用的方案?

  4. 我们如何隐藏自动生成的POCO属性不被篡改?

  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.

谢谢。

编辑

以下答案是有帮助的,但我仍然(理想情况下)寻找更多的想法。其他人?

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

推荐答案


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

  2. 如果我是你,我会将业务/域验证从数据层(EF)尽可能的如果有一个数据层验证场景,那么可以很好(例如,验证复杂的父/子关系 - 这纯粹是DB的东西)。

  3. 是的,复杂的业务验证应该在服务层或模型对象(附加,通过部分类或一些继承方法:interfaces /派生类)。有关ActiveRecord人员,存储库模式人员和DDD人员之间的争论,但与您有用的工作非常简单,并将实现快速部署和低成本应用程序维护。这是一个简单的如何你的例子可能会对域对象附加更复杂的验证,但仍然与 DataAnnotations 接口兼容,因此是MVC友好。

  4. 好问题 - 一个我还没有找到一个解决方案,我已经100%满意了。我已经玩了私人设置者的想法,这不是很好。快速阅读此总结的Evans DDD书籍。这是一个很好的快速阅读,它可能提供一些关于模型对象和值对象之间的目的和区别的洞察。这就是我认为对象设计将减轻您拥有的属性篡改(如您所说)的问题,但不会修复属性可见性。也就是说,其他解决方案可能在别的地方希望这有帮助。

  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.

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

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