Persistent Layer Validations - c#

While saving data using a stored procedure often we encounter foreign key constraints, unique key constraints, etc. All such errors can be corrected by passing in the right data.
Validation can be done in the business logic layer and should be sent to the persistence layer only if it succeeds. But in some cases it is convenient to validate data while saving. Like in a stored procedure.
Say for example if the user enters some date range values it should be validated that the range do not overlap any existing ranges. In such situation it is better to return some error code which can tell us if the range is overlapping and cannot be saved.
In SQL Server we can simply raise custom exceptions but I want to do it without using exceptions. Is there any validation frameworks already available which I can use.
I am looking for a SQL Server 2005 and .net specific solution.
P.S.: I generally return custom error codes from the Stored Procs and then parse them by looking up in an xml file and then use it in my Business Layer rules engine.

Embedding business logic in the SQL Server might improve the performance but it's going to complicate the design by violating seperation of concerns. In order for me to have portable business logic, it should be in the business layer. I would remove the validation logic from the stored procs and only use them to make CRUD operations easier. You never know when the project stakeholders are going to say "make it run on Database X!". Do your best to keep the validation logic database independent.

Related

which layer doest contain query for reading?

My project has 4 layers: Presentation, application, domain, infrastructure.
I am using ORM for the write side. Read side, sometimes I have cases that have a complex query. I process by using a native query.
I write it at the infrastructure layer. But, I see some projects such as "ESHOPONWEB" write a native query in application layers.
Which layer should contain the native query?
I wasn't familiar with ESHOPONWEB aka eShopOnWeb, a reference architecture & implementation that Microsoft put out, but I see it has an accompanying eBook which includes an "Architectural principles" section, another on "Common web application architectures", and at a glance other sections explain the architecture in more detail.
Using the book and code should give you a good way to learn the relevant concepts at your own pace.
Which layer should contain the native query?
I'm not 100% sure what you mean by "native query". I did a quick search through the eBook and didn't see any obvious references to that.
Typical best practice architecture (like what is in the eBook) says that queries in the Application / Business Logic layer should be agnostic - meaning they should not contain any code or dependencies that tightly-couples the Business Logic to a specific Data Access provider.
So, if you need to query a data base, the database specific query code (or reference to a Stored Procedure in the database or any other database specific concept) should be in the Data Access code, which is in the Data Access (Infrastructure) layer.
If something in your Business Logic layer wants to do a query, there's three approaches that come to mind:
It wants to query itself, which it is free to do, using agnostic code against objects it already has.
It wants to query data from the database, it gets the Data Access to do that. The query inputs and results need to be transported between these layers agnostically. E.g. query results might come back as a collection/array/list of Data Transfer Objects (DTO) or Plain Old CLR/Class Objects (POCO).
You take some section of data from your database / Data Access layer, pre-load that as a database agnostic data model in the Business Logic layer, which it can query just like #1.
I'm not sure, but your Domain layer might be what you can use to do #3?
Does that make sense, and answer your question?
Regarding Layers
As the eShopOnWeb book explains, you want to keep various "concerns" (like business logic, UI, and data access all separate. The separation is to make maintenance and change easier to manage, especially over a long time. E.g.:
Keeping the business logic layer/code separate from the UI layer/code means that you should be able to add new types of UI without having to re-write the application code.
Keeping the business logic layer/code separate from data access layer/code means that you should be able to add/swap data providers (e.g. different types of database), and the business logic should be less impacted by database changes.
In the two points, above I say "should" because it depends on how clean and effective your separation is.
To translate that to your layers, UI is obviously your Presenation layer, Business Logic sounds like your Application and Domain layers, Data Access is your Infrastructure layer.
In the eBook they give an example (fig 5-1, pg 16) where they logically have those four layers you use but in the one code-base / package (it will all get deployed together).

Must i check the user input in UI and Programming and T-SQL(with check constraint) side at the same time?

Or is the first two check fair enough for securing from hackers?And what about performance issues when i use check constraint in columns?
No, you do not have to check in all three places. However, your application and your database might be better off if you do.
Checking in the UI - especially with scripts or HTML - is very good for interactively showing the user how to correct their input. It saves a round trip to the web server, and is a performance enhancement because the user's CPU is used to run the validation code instead of the server.
Checking in the "programming" (here I believe you are referring to your business domain logic) is important if you ever want to add a new interface to your logic. For instance, if you have a well designed business layer that is consumed by a web application, later on you could also consume the same business layer with a WCF interface and have confidence that you aren't receiving invalid data.
And finally, validation rules in the database are important if you ever want to batch load data directly into the database. Perhaps a partner business or client sends you a text file that you need to load. Having the rules in place in the database will keep you from corrupting your data if the load routine has a defect.

Catching broken database contraints in C# - Best Practice

Say I have an SQL table that has a unique key (or other) constraint on one of the columns.
Then, I have an application (lets go ASP.NET MVC) that allows a user to edit this column.
When the user attempts to save, and the constraint is/will be broken, I need show a user-friendly error message to the user. As such, which of the following is better practice?
Have the application query the database to ensure the constraints are not broken, and then insert/update the row (results in two queries to the db)
OR
Immediately attempt to perform the insert/update, and catch the SqlException should the constraint be broken. I like this, because of only one trip to the db, however how should you then extract which index/constraint was broken and affix the appropriate message? (apart from inspecting Exception.Message?)
1 is the better all-around solution. Db calls are not the only expensive operation, exceptions are costly too. You should really only let your db throw an exception when something goes wrong due to your code, not a user action.
For example, you might later want to install Elmah and get exceptions logged and/or mailed to you. Elmah would log/mail such an exception unless you explicitly told it not to.
Plus like you said, exceptions don't always have the most businessy information to communicate to users (especially SQL exceptions, which are SQL-specific). You have these unique and other constraints for a reason. For those reasons, validate the information before trying to store it.
Take twitter, gmail, etc. When you go to get a username, the application first checks to see if it is taken. These are uniqueness constraints at the application level, which may or may not ultimately be realized as SQL constraints. Since it is your application that faces the user, you should not try to communicate to them by translating from SQL to English.
The problem with option 1 is that it requires the application to have separate distinct knowledge of what the constraints are, which conflicts with a DRY principle, and could lead to problems later when the database constraint gets changed, and the application is not updated - a tight coupling between the data logic, and the application. Also, there is no guarantee of the constraint checks that were performed are still valid at the subsequent pont when you then attempt the update.
This doesn't preclude augmenting your application with some UI layer validation to aid the user before the commit is attempted.
So if that is discarded we are left with option 2, and some translation is necessary somewhere in the application. Where you put that translation and that logic, whether in a Stored Procedurce or a Business Logic layer, is up to you.

Spreading of business logic between DB and client

Ok guys, another my question is seems to be very widely asked and generic. For instance, I have some accounts table in my db, let say it would be accounts table. On client (desktop winforms app) I have appropriate functionality to add new account. Let say in UI it's a couple of textboxes and one button.
Another one requirement is account uniqueness. So I can't add two same accounts. My question is should I check this account existence on client (making some query and looking at result) or make a stored procedure for adding new account and check account existence there. As it for me, it's better to make just a stored proc, there I can make any needed checks and after all checks add new account. But there is pros and cons of that way. For example, it will be very difficult to manage languagw of messages that stored proc should produce.
POST EDIT
I already have any database constraints, etc. The issue is how to process situation there user is being add an existence account.
POST EDIT 2
The account uniqueness is exposed as just a simple tiny example of business logic. My question is more abour handling complicated business logic on that accounts domain.
So, how can I manage this misunderstanding?
I belive that my question is basic and has proven solution. My tools are C#, .NET Framework 2.0. Thanks in advance, guys!
If the application is to be multi-user ( i.e. not just a single desktop app with a single user, but a centralised DB with the app acting as clients maybe on many workstations), then it is not safe to rely on the client (app) to check for such as uniqueness, existance, free numbers etc as there is a distinct possibility of change happening between calls (unless read locking is used, but this often become more of an issue than a help!).
There is the ability of course to precheck and then recheck (pre at app level, re at DB), but of course this would give extra DB traffic, so depends on whether it is a problem for you.
When I write SPROCs that will return to an app, I always use the same framework - I include parameters for a return code and message and always populate them. Then I can use standard routines to call them and even add in the parameters automatically. I can then either display the message directly on failure, or use the return code to localize it as required (or automate a response). I know some DBs (like SQL Svr) will return Return_Code parameters, but I impliment my own so I can leave inbuilt ones for serious system based errors and unexpected failures. Also allows me to have my own numbering systems for return codes (i.e. grouping them to match Enums in the code and/or grouping by severity)
On web apps I have also used a different concept at times. For example, sometimes a request is made for a new account but multiple pages are required (profile for example). Here I often use a header table that generates a hidden user ID against the requested unique username, a timestamp and someway of recognising them (IP Address etc). If after x hours it is not used, the header table deletes the row freeing up the number (depending on DB the number may never become useable again - this doesn;t really matter as it is just used to keep the user data unique until application is submitted) and the username. If completed correctly, then the records are simply copied across to the proper active tables.
//Edit - To Add:
Good point. But account uniqueness is just a very tiny simple sample.
What about more complex requirements for accounts in business logic?
For example, if I implement in just in client code (in winforms app) I
will go ok, but if I want another (say console version of my app or a
website) kind of my app work with this accounts I should do all this
logic again in new app! So, I'm looking some method to hold data right
from two sides (server db site and client side). – kseen yesterday
If the requirement is ever for mutiuse, then it is best to separate it. Putting it into a separate Class Library Project allows the DLL to be used by your WinForm, Console program, Service, etc. Although I would still prefer rock-face validation (DB level) as it is closest point in time to any action and least likely to be gazzumped.
The usual way is to separate into three projects. A display layer [DL] (your winform project/console/Service/etc) and Business Application Layer [BAL] (which holds all the business rules and calls to the DAL - it knows nothing about the diplay medium nor about the database thechnology) and finally the Data Access Layer [DAL] (this has all the database calls - this can be very basic with a method for insert/update/select/delete at SQL and SPROC level and maybe some classes for passing data back and forth). The DL references only the BAL which references the DAL. The DAL can be swapped for each technology (say change from SQL Server to MySQL) without affecting the rest of the application and business rules can be changed and set in the BAL with no affect to the DAL (DL may be affected if new methods are added or display requirement change due to data change etc). This framework can then be used again and again across all your apps and is easy to make quite drastic changes to (like DB topology).
This type of logic is usually kept in code for easier maintenance (which includes testing). However, if this is just a personal throwaway application, do what is most simple for you. If it's something that is going to grow, it's better to put things practices in place now, to ease maintenance/change later.
I'd have a AccountsRepository class (for example) with a AddAcount method that did the insert/called the stored procedure. Using database constraints (as HaLaBi mentioned), it would fail on trying to insert a duplicate. You would then determine how to handle this issue (passing a message back to the ui that it couldn't add) in the code. This would allow you to put tests around all of this. The only change you made in the db is to add the constraint.
Just my 2 cents on a Thrusday morning (before my cup of green tea). :)
i think the answer - like many - is 'it depends'
for sure it is a good thing to push logic as deeply as possible towards the database. This prevent bad data no matter how the user tries to get it in there.
this, in simple terms, results in applications that TRY - FAIL - RECOVER when attempting an invalid transaction. you need to check each call(stored proc, or triggered insert etc) and IF something bad happens, recover from that condition. Usually something like tell the user an issue occurred, reset the form or something, and let them try again.
i think at a minimum, this needs to happen.
but, in addition, to make a really nice experience for the user, the app should also preemptively check on certain data conditions ahead of time, and simply prevent the user from making bad inserts in the first place.
this is of course harder, and sometimes means double coding of business rules (one in the app, and one in the DB constraints) but it can make for a dramatically better user experience.
The solution is more of being methodical than technical:
Implement - "Defensive Programming" & "Design by Contract"
If the chances of a business-rule being changed over time is very less, then apply the constraint at database-level
Create a "validation or rules & aggregation layer (or class)" that will manage such conditions/constraints for entity and/or specific property
A much smarter way to do this would be to make a user-control for the entity and/or specific property (in your case the "Account-Code"), which would internally use the "validation or rules & aggregation layer (or class)"
This will allow you to ensure a "systematic-way-of-development" or a more "scalable & maintainable" application-architecture
If your application is a website then along with placing the validation on the client-side it is always better to have validation even in the business-layer or C# code as well
When ever a validation would fail you could implement & use a "custom-error-message" library, to ensure message-content is standard across the application
If the errors are raised from database itself (i.e., from stored-procedures), you could use the same "custom-error-message" class for converting the SQL Exception to the fixed or standardized message format
I know that this is all a bit too much, but is will always good for future.
Hope this helps.
As you should not depend on a specific Storage Provider (DB [mysql, mssql, ...], flat file, xml, binary, cloud, ...) in a professional project all constraint should be checked in the business logic (model).
The model shouldn't have to know anything about the storage provider.
Uncle Bob said something about architecture and databases: http://blog.8thlight.com/uncle-bob/2011/11/22/Clean-Architecture.html

Software Design - Three-tier architecture

Layer 3 - Interface
Layer 2 - Business logic (get input from user, check if valid, send to database function)
Layer 1 - Database (creates, updates, gets records etc)
A user can add many contact phone numbers, if it is the first phone number added the system will automatically set that phone number to primary, and there after the user can change his primary phone number on his own.
When the first phone number record is created in the database, which layer is responsible to check if the phone number needs to be set to primary or not?
Business layer. The database should be storing data, not making decisions. The interface just interacts with the user. The business layer makes the rules.
Your business logic should handle it when the phone number gets added to the user. You can verify it works by providing unit/integration tests for it.
I guess it depends what you're aiming for. As it is your business layer should handle phone being validated/set as primary. Database would still need to store that information in some way I think.
However in certain cases like security verification you'll need to do some checks at Interface, Logic and Database level. Yes it is redundant but I think you'll want to guarantee that hackers that break your interface or logic, can't go around messing with your underlying data.
The data layer in an N-tier application isn't really supposed to do anything other than to put values in and get values in. Think of it as an persistence service.
Everything else goes into what's known as the business and/or logic layer except for UI code (you're supposed to keep those things separate in following something like MVP, MVC or MVVM).
Though this simple problem actually raises a issue with transactions, your data model should eventually prevent this, but if you cannot complete the operation as an atomic unit there always the chance that two phone numbers are put at the same time and they both end up as primary (depending on the latency between the application and database). To gracefully handling these situations you need at least think about error recovery (error handling) that propagates these problems in a meaningful manner. Don't just crash your application.
Just to add to the above answers, you might want to consider persisting input regardless of validity. Can add a bit more development (especially if you need to clean the data) but it can be worth it depending on your application

Categories

Resources