views:

31

answers:

3

Data stored in relation database with data constraints (for example maximum string property length). Clients use Data Access Library (DAL) to manage the data in ORM manner (repositories + data domain classes)

Where would you personally implement constraints? For example:

Data domain classes:

class Person
{
 private string _name;
 public string Name 
 {
   get { return _name; }
   set { _name = StringHelper.Truncate(value, 50) }
 }
 ...
}

Or may be repository:

PersonRepository {
  public void CreatePerson(Person p) {
    p.Name = StringHelper.Truncate(p.Name, 50);
    ... 
    DataContext.Insert(..);
  }
}

Or may be you shall use attributes assigned to data domain classes properties that would be processed in repository methods via reflection for automated string fields truncation.

class Person {
   [StringConstraint(MaxLength = 50)]
   public string Name { get; set; }
} 

PersonRepository::CreatePerson(p) {
  EntityHelper.ApplyConstraints(p);
  ...
}

Or may be something else?

Thank you in advance!

A: 

In the database is my preference.
If someone attempts to insert a string that's too long, a SQL error will be returned. It's up to the application to handle that error by displaying a useful msg to the user.

It's also centralized in case someone has alternate access - SSMS, or other application code.

OMG Ponies
Andrew Florko
OMG Ponies
I understood, but it would much more user-friendly just to deny enter lengthy strings instead of time consuming ui-dbms roundtrips with any kind of error messages ("Hey! Your name is too long! Please, remove 10 chars") . For my opinion constraints should be bubbled from dbms level.
Andrew Florko
@Andrew Florko: That would mean more than one place that holds that length/etc value - you've created a redundancy that needs to be synchronized to be of any value.
OMG Ponies
Yes, that's true. But developing comfort (centralized constraints) has no value to customers. They should have responsive, smart UI.
Andrew Florko
@Andrew Florko: Users also shouldn't be subject to false positive errors, like when someone updates the UI without updating the database. If necessary, *cache* the meta data on startup
OMG Ponies
hmm.. sounds interesting, ok
Andrew Florko
+1  A: 

I would do it in the business logic layer, with a business logic class that is different from the database related classes. I wouldn't bubble up the sql error or even enforce it in the database. In my opinion the database should only be concerned with the shape and consistency of the data. Not with the actual data itself.

Your rule about 50 characters is a business rule, not a logical, relational or "structural" rule. It could just as easily be 51 characters or 49. You arbitrarily picked 50, which is fine. That is what the business layer objects are there for. To enforce those rules.

Any business access to your data, should again be through the business layer, exposed via services, direct reference or some other method you choose.

The only "direct" access to your database should again be things which care about the shape and consistency of your data, not the actual data itself. Things like backup, replication, clustering, load balancing, auditing etc.

So the ORM classes are just the glue between a business object of Person and the storage of Person in an actual database. The database should only care about the overall shape and structure of the database and the underlying infrastructure and mechanics of the actual data storage. The business object should determine the "nature" of the object and define what it truly is. That a Person should always have at least a firstname, that their age cannot be greater than 110 years, their height cannot be more than 7 feet, etc. etc.

Thats my philosophy/rule of thumb anyway :-)

Chaitanya
Ok, thank you for the philosophy :)
Andrew Florko
So now when the length changes, you need to update two places - the database, *and* the business layer...
OMG Ponies
Thats why I said that I wouldn't even bother putting the validation in the database. The database shouldn't look at the data itself only the logical structure i.e that one Person can be related to many Orders and the underlying infrastructure. Update to person triggers and entry into another table. And about "centralizing in case someone has alternate access", see my paragraphs about business via BL layer vs Direct access for Database operations
Chaitanya
+1  A: 

Constraints are part of validation. It is responsibility of Business layer to validate objects but it is also convenient to use same validation logic in UI. The way to share such logic is to use some API which marks your data objects with validation attributes. You can than run the same validation in BL and UI. DataAnnotations offers this functionality and it can be also achieved with Validation application block.

Edit: It doesn't mean that you will not place constraints in DB. This only mean that you should be able to detect constraint violation as soon as possible to save the round trip to database.

Ladislav Mrnka
Where would you personally put DataAnnotation attributes? To "data domain" classes or make another layer of classes?
Andrew Florko
This is based on complexity of your application an supposed design. This approach works best if you use simple objects shared between all layers. If you use different set of object for each layer you have to duplicate validation for each set (example: validation for Domain objects which are not exposed to UI and another validation for DTO objects exposed to UI).
Ladislav Mrnka