以下是该方案:
所以基本上,所有很酷的东西。 :)
基本UI操作的事件流程(“添加帖子”):
现在,我正在尝试找出可以进行验证的地方。
在这个阶段,我需要两种类型的验证:
现在,我一直在阅读Julie Lerman撰写的“编程实体框架,第二版”(这是一个优秀的BTW),并且一直在研究挂钩SavingChanges事件,以便执行“最后一分钟”验证。这是确保验证总是在我做“某事”(添加,修改,删除)时发生的一种很好的方法,但它也有点晚了IMO(因为项目已经在状态管理器中) - 如果验证失败,我该怎么办,删除它们?
我当然可以让我的POCO实现一个接口(比如“IValidatable”),并在此事件中调用此接口上的方法。
但对于业务验证来说,这似乎“为时已晚” - 这是共识吗?
我基本上在这里寻求指导,我正在尝试为复杂的业务逻辑设计一个可重用的智能验证方案,给出了我的上述架构。
另一个曲线球对你来说 - 如你所知,POCO与EF意味着POCO拥有数据库中的所有属性 - 所以我可能有一个“PostID”属性,带有get / set访问器(因为EF需要获取/设置这些属性)。
但问题是,“PostID”是一个身份列,那么我如何保护该字段不被明确设置?例如,如果我(出于某种原因)执行以下操作:
var post = service.FindSingle(10);
post.PostId = 10;
unitOfWork.Commit();
这会抛出一个SqlException。我该如何防止这种情况?我不能“隐藏”该属性(使其成为私有属性,甚至是内部属性),因为POCO与存储库分开组装。
关于验证的说明 - 我打算创建自定义异常(从Exception派生)。因此,当验证失败时,我需要抛出这些异常。
这样,我可以在我的控制器上编写类似的代码:
[HttpPost]
public ActionResult AddPost(Post post)
{
try
{
IUnitOfWork uow = new UnitOfWork();
postService.Add(post);
uow.Commit();
}
catch(InvalidPostOperation ipo)
{
// add error to viewmodel
}
}
每次添加时,我是否必须在服务层上手动进行验证?那我该如何处理Save? (因为这是工作单元,而不是服务层)。
所以为了防止这是一个“到处都是”的问题,这是我的问题:
任何想法都会受到最高的赞赏。
如果这篇文章“太长”,请道歉,但这是一个重要问题,并且可以通过多种方式解决,所以我想提供所有信息以便获得最佳答案。
感谢。
修改
以下答案很有帮助,但我仍然(理想情况下)寻找更多想法。还有其他人吗?
答案 0 :(得分:1)
DataAnnotations
不适合所有情况。根据我的经验,缺点主要是复杂的验证(多个属性和多个属性不同的对象)。DataAnnotations
接口兼容,因此是'MVC友好'。答案 1 :(得分:1)
这完全取决于您的架构,即您的应用程序中是否存在逻辑分离:UI,服务层,存储库层。如果您正在关注Save事件,那将如何完成?根据我的观察,你只会调用存储库Layer for Persistance吗?但是,您正在连接到保存事件,将控制权交还给服务层/业务层,然后通过权限强制保存?
我个人认为服务层/业务层应该在完成时处理它然后说,嘿先生的repo层 - >保存这个对象。
关于验证,数据注释应该与UI一起使用,如[Required]等简单的valiation,这将有助于客户端验证,但复杂的业务逻辑或复杂的验证应该挂钩到服务层/业务层,这样它可以在所有实体/对象/ POCOS等中重复使用。
关于防止某些私有字段未被篡改...只允许您的服务层/业务层实际设置将被持久化的对象(是的,我的意思是:) ...)手工编码,我觉得无论如何,这对我来说是最安全的选择,我会这么做:
var updatedpost = _repo.GetPost(post.postid);
updatedpost.comment = post.comment;
updatedpost.timestamp = datetime.now;
有点浪费,但这样你的buseinss层控制,但这只是我的经验我可能是错的,我已经阅读了很多关于模型绑定,validaiton和其他的东西,但似乎有一些事情,事情永远不会工作预期的例如[必填]属性(见Brad WIlson的)帖子。