Storing reporting assemblies (.net) in a database - c#

I'm developing a project where users need to build reporting queries using complex Linq statements to generate data sets.
The best way I could think of to compile these user-generated queries and then execute them is to use the CSharpCodeProvider object to build an assembly and then store the result in a database blob.
Is there anything wrong with this process? Also, how can I restrict the permissions of the user assembly to only allow execution against a limited set of objects that I provide?
Thanks!

You shouldn't have to save the queries as a generated assembly. A simpler way would be to save the SQL executed against the database for future use. Use the GetCommand method of the DataContext to get the SQL and persist it as a "saved" query.

Related

Database validation in application

I have a c# application add-on from which I need to validate the schema of a database. I can't use any of the obvious frameworks due to limitations of the application I'm extending, but rather need to find an alternative method to confirm whether database procedures exist and or whether they need to be updated (if the procedure itself was changed from what is expected). Aside from writing individual queries for each procedure are there any better solutions I might consider?
There is database project in visual studio. You can import your database to this project and try to build. Please see official documentation:
https://learn.microsoft.com/en-us/sql/ssdt/import-into-a-database-project?view=sql-server-2017
<twocents>
Export all your objects to .SQL files and commit them to source control and write them out into a folder on disk.
Create a tracker table that maps the object you have exported to a hash of the DDL of the object.
Inspect the objects in the database when your app initialises or at some other appropriate time.
Compare the hash of the DDL of the database object in the database with what is on the disk. If there is a disparity drop and recreate the object by executing the DDL of the file on disk
The hash acts as fast way to check if what's in the database matches the structure of the object that you expect to be in the database. How you deploy it is questionable, but the assumption I am making is that you are in control of your database objects that you have exposed to the application.
</twocents>

Effective storing of SQL queries in C# Visual Studio projects

I have about 20 (relatively) big queries hardcoded in my C# code that I would like to move somewhere else, as they are now making my code look unmanageable. These SQL queries have in common that they receive a fixed set of parameters (2 parameters to be precise).
I am looking at ways of where to place them in my project and how to manage them, and so I was thinking of creating separate sql files for each query in a folder in which the code would look into, somehow passing these two parameters before actually executing the query.
The question is the following. Are there any standard/efficient ways of performing the above in C#? I really do not like these SQL queries hard-coded in my projects, but I am also mindful that these would be parametrised queries and so I might not be able to achieve the above.
Any guidance or help would be most welcome. In case it helps, I do not have access rights to write stored procedures to solve this situation.
Too bad that it has to be a query not stored procedure
If it is not possible to execute stored procedures then you can put the queries in text files and all those text files can be loaded in a resource file. You can access them with "resourceFileName.TextFileName" and please keep the parameters with # and their names.
you can load the query with
using System.Resources;
var resourceManager = new ResourceManager("resourceFileName", Assembly.UnsafeLoadFrom("resourceDll"));
string myQuery= resourceManager.GetString("TextFileName");

How can I prevent users running UPDATE statements via a query builder

We are building a reporting framework into our application, which necessitates the use of a query builder. Ultimately, we want power users to be able to build SELECT queries to be used to populate the report dataset.
Datasets are built using a DataAdapter (either MSSQL or SQLite). Are there any tools we can use to ensure that the queries built by the end user can only be SELECT statements?
EDIT:
As mentioned above, we target SQLite as one of our supported backends No DB permissions can be set on this platform.
Set right permissions to DB. It's the best solution.
EDIT:
For SQLLite you can set read only permissions for file - in the file system.
Give the user that you execute the SQL as only the db_datareader permission to ensure that they cannot do anything but read the data.
This question gives more info on how to do that:
How to give a user only select permission on a database
If the query builder is done in house, and if your query builder returns a the SQL statement in a string, you can parse it either looking for Update statements keyworks or with Regex, if you want to spare the users the trouble of creating an update query then realizing that they can't run it, then you should consider doing this check continiously as they create the query. Alternatively, you can use a third party query builder, like this one: http://www.activequerybuilder.com/, unfortunately i belive it doesn't support anything else but Select statements but it may be worth the shot.
I think all you have to do is wrap the QueryBuilder and expose only permited operations.
I is not good to do thinks the other way around, like letting the user construct a query and at the end you tell him it is not permissable.

Where do you put SQL Statements in your c# projects?

I will likely be responsible for porting a vb6 application to c#. This application is a windows app that interacts with an access db. The data access is encapsulated in basic business objects. One class for one table basically. The existing vb6 business objects read and write to the DB via DAO. I have written DALs and ORMs a few times before but they all targeted SQL Server only. This one will need to target access and sql server. In previous projects, I would place the SQL strings in the private parts of the business object and maybe move the redundant sql code like connecting, creating command, in into a common base class to reduce the code.
This time, i'm thinking about writing the SQL strings into a .settings file or some other key/value type text file. I would then write a sql utility to edit this file and allow me to run and test the parameterized queries. These queries would be referenced by name in the business object instead of embedding the sql into code.
I know a standard approach is to create a DAL for each targeted database and have the configuration state which DAL to use. I really don't want to create the two DAL classes for each database. It seems like it would be less code if I just referenced the correct query by keyname and have the proper type of connection.
So, are you guys doing things like this? How would or have you approached this problem?
What works best for you?
Thanks!
Well, there's a lot of options - so it really depends on what your most pressing needs are :-)
One approach might be to create SQL statements as text files inside your VS solution, and mark them as "embedded resource" in the "build action". That way, the SQL is included in your resulting assembly, and can be retrieved from it at runtime using the ResourceManifestStream of the .NET framework:
private string LoadSQLStatement(string statementName)
{
string sqlStatement = string.Empty;
string namespacePart = "ConsoleApplication1";
string resourceName = namespacePart + "." + statementName;
using(Stream stm = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
if (stm != null)
{
sqlStatement = new StreamReader(stm).ReadToEnd();
}
}
return sqlStatement;
}
You need to replace "ConsoleApplication1" with your actual namespace, in which the sql statement files reside. You need to reference them by means of the fully qualified name. Then you can load your SQL statement with this line:
string mySQLStatement = LoadSQLStatement("MySQLStatement.sql");
This however makes the queries rather "static", e.g. you cannot configure and change them at runtime - they're baked right into the compiled binary bits. But on the other hand, in VS, you have a nice clean separation between your C# program code, and the SQL statements.
If you need to be able to possibly tweak and change them at runtime, I'd put them into a single SQL table which contains e.g. a keyword and the actual SQL query as fields. You can then retrieve them as needed, and execute them. Since they're in the database table, you can also change, fix, amend them at will - even at runtime - without having to re-deploy your whole app.
Marc
When I really need it, I put the queries into individual *.sql files, then include them into Resources.resx. There is a 'Files' section in it, which allows you to include Embedded Resource files.
After that, I can use generated Resources.MyQuery property which both guarantees that resource exists and saves me from writing a custom resource load method.
LINQ to DataSet sounds like the way to go for you.
If you havent used the .NET 3.5 before / LINQ then you're in for a treat. LINQ will save you writing your raw sql in string literals and provide you with a more logical way to creating querys.
Anyway, check this link out for using LINQ on Access databases - http://msdn.microsoft.com/en-us/library/bb386977.aspx
If i'd had to create application for both SQL and Access, I'd use some IDAL interface, DALCommon with common functionality implementation and separate DALSql and DALAccess, inherited from DALCommon, with some specific stuff, like exceptions, transactions handling, security etc.
I used to keep stored procedure names or queries in resource files.
I'll tell where I won't put it ever, something I saw done in some code I inherited. It was in Java, but applies to any language
A base class that declared protected static member variables for for SQL statements, inited to null, with a get method that returns individual SQL statements
A sub class for each supported database server, with an init method that assigns to the base class member variables
Several DA classes that use the base class method to retrieve SQL statements
The application start-up class with the responsibility to create the correct sub-class object and call its init method
I will also not go into explaining why I will not do this ever :-)
One method we used is to have a class that would connect to the DB and methods to call procedures and in the method parameter you would provide the procedure name. so all the SQL code is in the procedure. we would use overloads for the different return types
class ConnectToSQL()
{
//connectSql code (read from setting file i assume)
XMLDataDocument runProcedure(string procedureName);
int runProcedure(string procedureName);
//etc....
}
Sometimes, like with custom reporting apps, you really need to embrace the impedance mismatch, and give special importance to the SQL. In these cases I recommend the following: For each module that contains SQL strings, create a single static "SQL" class to hold them all. Some of the SQL strings will likely require parameters, so be consistent and put each string behind it's own static method.
I only do this for the occasional custom reporting app, but it always works out great and feels refreshing and liberating. And it's quite nice to come back months later to make an enhancement, and find all of the SQL waiting for you in a single SQL.cs file. Just by reading that one file, it all comes back, and often this is the only file that needs to be changed.
I don't see a need in these cases for hiding the SQL in resources or elsewhere. When SQL is important, then it's important. Interestingly, more and more developers are now freely mixing SQL with C#, including I believe this site, because essentially, that's what LINQ is.
Finally, as always, make sure you are not susceptible to SQL injection attacks. Especially if user input is involved, make sure you are using some kind of parameterization and that you are not using string concatenation.
Embedding solutions shown above may not work if SQL Query has a "where" cause like , but for the same Query the next run needs PropertyID='113' as the PropertyID is read-in.
Glad you asked! Put your sql in a QueryFirst .sql template.
It's automatically compiled into your app as an embedded resource, but you don't care. You just write it, in a real sql window, connected to your DB, with syntax validation and intellisense for tables and columns, then use it, via the generated Execute() methods, with intellisense for your inputs and results.
disclaimer : I wrote QueryFirst.

LINQ to SQL Cannot create database [Schema Permissions]

For some integration tests I want to use LINQ to SQL to drop/re-create the test database. I've had this working fine before, however in this project the database is split up into several schemas.
When I try to run the ctx.CreateDatabase() command I'm getting this exception:
The specified schema name "xyz" either
does not exist or you do not have
permission to use it.
The login I'm using to do this has the role dbcreator - Does it need further permissions? Surely a login with persmissions to create a database should be able to create everything contained in that database also?
Update:
Since it looks like there isn't a solution to this problem using LINQtoSQL, does anyone have recommendations of any similiar tools to generate a db that are preferably free? Ideally I don't want to have to muck about hand writing sql build scripts.
From what I've read, the CreateDatabase() method is limited in what it can reproduce of the original database. It won't recreate things like triggers and check constraints, and I'm guessing it doesn't create custom schemas either. You may want to look into creating the database using a SQL Server .mdf file instead to work around this issue. See this blog entry for more details on some of the limitations of CreateDatabase().
I generally do this sort of work in NAnt to create, initialize the database, create users, add logins, etc....and also roll back capabilities. I have written on this topic quite a bit if you are interested:
Build automation with NAnt
Continuous integration with CruiseControl.NET
I will have to see if I can get LINQ to SQL to work in the way you are trying to use it...that sounds like what we used to do with NHibernate.
The dbcreator fixed server role grants you the permission to create a database. If you create a database, you are the dbo of said database and as dbo you have absolute power in the database, includding the power to create, alter and drop any schema and any object contained in any schema.
the problem with LINQ's CreateDatabase() is not permission, is code quality. The generated SQL code simply does not create the needed schema, so the Create table statements fail because the schema does not exist.
Your best choice, if you can afford it, is to add a VSTS Database Edition GDR R2 project to your solution and declare all your database objects in the Database Edition project (part of your solution). You'll be also getting the added benefit of storing all your database objects in a proper source control solution. The output of the Database project would be a .dbschema file containing the definition of your database. At deployment time (test or real) you would run the VSDBCMD Deployment and Schema Import tool to import your .dbschema into the target server. The tool is capable of doing initial deployment of your schema, as well as further upgrades (deploy only differences). The VSDB solution would allow you to controll all your database objects: tables, indexes, views, schemas, field contraints, table constraints, triggers, procedures, users, permissions, logins etc etc. It really covers all the objects that can be defined in SQL Server.
Actually LINQ to SQL does support schemas, but not every Sql Server edition does. To enable CreateDatabase() to generate them the DataContext must be aware that the target database does support them. It can be done by setting the provider on the DataContext:
[Provider(typeof(Sql2008Provider))]
public class CustomDataContext : DataContext {
...
}
Your user also requires db_dlladmin for that database.
I would definately look at Entity Framework, which I am beginning to look into these days. It's an OR/M, and will most definately suit your needs, and alot more once the next version is released.
Entity Framework is also a brain-child of Microsoft and can be found here: http://msdn.microsoft.com/en-us/library/aa697427(VS.80).aspx
One thing to remember between LINQ to SQL and LINQ to Entities is that you are programming against a model, and not the database.

Categories