I work on a ancient large WinForms project that contains a lot of win form libraries.
Each form uses hard-coded sql commands in methods. Sometimes the same SQL strings are duplicated, and modifying one I should research “similar” strings in the form’s code.
I understand that the architecture is not super-pretty, but at moment we can’t perform large architecture modifications. I think to do “little steps” to ameliorate the separation o the UI and BD logic….
A first ‘step’, by eg. I thought “separate” in a way sql strings from code. How could this be achieved, using Resources, a special class, a XML file?
Variant I – using named Resources
' ancient variant '
_SqlPeriod = String.Format("SELECT * FROM DBO.GP_PERIOD WHERE PERIOD = {0} ORDER BY LABEL", Me._Period)
' a better way (?) ... '
_SqlPeriod = String.Format(My.Resources.ResourceManager.GetString("SelectAPeriod"), Me._Period)
Generally, your biggest concern is using
String.Formatto form your SQL queries, because this is prone to Sql Injection Attacks, if you don’t explicitly validate your parameters. So separating these strings is not an improvement (and moving them into an xml file would be a security disaster, if they are resolved during runtime).To prevent this, you need to either create
SqlCommandinstances and set parameters programatically (check MSDN – How To: Protect From SQL Injection in ASP.NET), or use a completely different approach and switch to an ORM framework.Since moving to ORM might take considerable amount of time if you haven’t used it before, I believe you will opt for the first option. In that case, simply switching to Sql parameters as described above will be an improvement (even with sql strings left hard-coded).
To prevent duplication, you should consider moving all database access calls into a separate project (a Data Access Layer, DAL). If you want to start in smaller steps, you might consider (for start) delegating the creation of the SQL string to a different layer, e.g.:
This would allow you to move parameter validation into a common project. Later, you will want to avoid passing sql strings to your UI layer completely, and simply get the data: