design patterns - Advice on POCO Validation with ASP.NET MVC/Entity Framework -
here's 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, cool stuff. :)
flow of events basic ui operation ("adding post"):
- controller calls add(post) method on service layer
- service layer calls add(t) on repository
- repository calls addobject(t) on custom data context
- controller calls commit() on unit of work
now, i'm trying work out can put validation.
at stage, need 2 types of validation:
- simple, independant poco validation such "post must have title". seems natural fit data annotations on poco's.
- complex business validation, such "cannot add comment locked post". can't done data annotations.
now, have been reading "programming entity framework, second edition" julie lerman (which excellent btw), , have been looking hooking savingchanges event in order perform "last-minute" validation. nice way ensure validation always happens whenever "something" (add, modify, delete), it's little late imo (as items in state manager) - can if validation fails, remove them?
i of course make poco's implement interface (say "ivalidatable"), , call method on interface during event.
but seems "too late" business validation - consensus?
i'm looking guidance here, i'm trying design re-usable, intelligent validation scheme complex business logic, given above architecture.
another curve-ball - know, poco's ef mean poco's have properties on db - might have "postid" property, get/set accessors (as ef needs get/set these properties).
but problem is, "postid" identity column, how protect field being explicity set? e.g if (for reason) following:
var post = service.findsingle(10); post.postid = 10; unitofwork.commit();
this throw sqlexception. how can prevent this? can't "hide" property (make private, or internal) poco's in seperate assembly repository.
a note on validation - i'm planning create custom exceptions (deriving exception). when validation fails, need throw these exceptions.
that way, can code on controller:
[httppost] public actionresult addpost(post post) { try { iunitofwork uow = new unitofwork(); postservice.add(post); uow.commit(); } catch(invalidpostoperation ipo) { // add error viewmodel } }
will have manually validation on service layer everytime add? how can handle save? (as on unit of work, not service layer).
so prevent being "all on place" question, here questions:
- simple poco validation - should done data annotations? pros/cons/gotchas?
- under circumstances (if any) should hooking savingchanges event of ef data context in order provide validation?
- where should performing complex business validation? in service explicity, or method on poco's (which can call service). how can create intelligent/reusable scheme?
- how can "hide" auto-generated properties of poco's being tampering with?
any thoughts appreciated.
apologize if post "too long", it's important issue , 1 can solved in many ways, wanted provide info in order best possible answer.
thanks.
edit
the below answer helpful, i'm still (ideally) looking more thoughts. else?
- well said,
dataannotations
not appropriate situations. cons complex validation (multiple property , multiple property different object) in experience. - if you, leave business/domain validation out of data layer (ef) as possible. if there data layer validation scenario, fine (eg. validating complex parent/child relationships - purely db stuff).
- yes, complex business validation should in service layer or in model objects (attached, via partial classes or inheritance approach: interfaces/derived classes). there's debate between activerecord people, repository pattern people , ddd people, go works you, simple , enable rapid deployment , low cost application maintenance. simple example of how might attach more complex validation domain objects yet still compatible
dataannotations
interface , 'mvc friendly'. - good question. -one have not found solution i'm 100% happy yet. have played idea of private setters , it's not great. have quick read of summarized evans ddd book. it's great quick read , might provide insight purpose , difference between model objects , value objects. think object design mitigate problems having property "tampering" (as call it) without fixing property visibility. ie, solution might lie elsewhere. hope helps.
Comments
Post a Comment