I've written an ASP.NET application that uses SQL SERVER Database. During modification of the Database, an experienced guru in .NET+DBMS said, one of the problems of relating/mapping multiple tables could be elegantly solved with .NET XML strings. I've never heard of this technique, but not to sound ignorant of such "hacks", I cannot ask him about it. Is there a way to INSERT/UPDATE/DELETE XML strings like a regular database table(without using Linq to XML)?
If it's not Linq to XML, then he may mean XML Columns. SQL Server 2005 onwards lets you define XML Columns in your tables. So you can have actual XML in fields in the table and you can then perform XQuery operations on them.
I do not know what your context is and what the problem statement is so I cannot tell you if this is a good or bad idea. It has its uses and can be useful in certain cases, but not in an extensive, scalable way. It really depends on what you will be using it for.
I am not sure what he meant, but it's possible to serialize your object to XML and pass the XML as a parameter to a Stored Procedure.
DECLARE #PersonJobsXML XML
SELECT #PersonJobsXML = '<PersonJobs>
<PersonId>24234</PersonId>
<Job>
<JobTitle>Engineer I</JobTitle>
<CompanyName>ACME</CompanyName>
</Job>
<Job>
<JobTitle>Engineer II</JobTitle>
<CompanyName>World Inc.</CompanyName>
</Job>
<Job>
<JobTitle>Engineer II</JobTitle>
<CompanyName>Tek Corp</CompanyName>
</Job>
</PersonJobs>'
SELECT PersonJobs.Job.value('../PersonId[1]', 'INT') AS PersonId
, PersonJobs.Job.value('JobTitle[1]', 'VARCHAR(200)') AS JobTitle
, PersonJobs.Job.value('CompanyName[1]', 'VARCHAR(200)') AS CompanyName
FROM #PersonJobsXML.nodes('//PersonJobs/Job') AS PersonJobs ( Job )
This allows you to pass a list of object to the database with just one call; the downside is that the size could be quite limited
But If you are using SQL server 2008 you should look at Table-Valued Parameters: see Table Value Parameters in SQL Server 2008 and .NET (C#)
Related
Is it possible to pass a database field, for example MyTable.EmpoyeeID as a parameter in SQL query using Command? MyTable.EmpoyeeID value will be defined using ASP. net.
Sample:
SELECT FName, MName, LName FROM MyTable WHERE EmpoyeeID = MyTable.EmpoyeeID
option 1: yes, but you need to use aliases and, if memory serves the behavior tends to change across Crystal version. Google the topic of Crystal Reports, SQL Expressions, and Correlated Subqueries. You should find several in-depth threads.
option 2: use a 3rd-party UFL (User Function Library) that allows you to call arbitrary SQL statement you create inside a Crystal formula (not just SELECT statements are supported using that approach).
My situation
I have a c# object which contains some lists. One of these lists are for example a list of tags, which is a list of c# "SystemTag"-objects. I want to instantiate this object the most efficient way.
In my database structure, I have the following tables:
dbObject - the table which contains some basic information about my c# object
dbTags - a list of all available tabs
dbTagConnections - a list which has 2 fields: TagID and ObjectID (to make sure an object can have several tags)
(I have several other similar types of data)
This is how I do it now...
Retrieve my object from the DB using an ID
Send the DB object to a "Object factory" pattern, which then realise we have to get the tags (and other lists). Then it sends a call to the DAL layer using the ID of our C# object
The DAL layer retrieves the data from the DB
These data are send to a "TagFactory" pattern which converts to tags
We are back to the Object Factory
This is really inefficient and we have many calls to the database. This especially gives problems as I have 4+ types of lists.
What have I tried?
I am not really good at SQL, but I've tried the following query:
SELECT * FROM dbObject p
LEFT JOIN dbTagConnection c on p.Id= c.PointId
LEFT JOIN dbTags t on c.TagId = t.dbTagId
WHERE ....
However, this retreives as many objects as there are tagconnections - so I don't see joins as a good way to do this.
Other info...
Using .NET Framework 4.0
Using LINQ to SQL (BLL and DAL layer with Factory patterns in the BLL to convert from DAL objects)
...
So - how do I solve this as efficient as possible? :-) Thanks!
At first sight I don't see your current way of work as "inefficient" (with the information provided). I would replace the code:
SELECT * FROM dbObject p
LEFT JOIN dbTagConnection c on p.Id= c.PointId
LEFT JOIN dbTags t on c.TagId = t.dbTagId
WHERE ...
by two calls to the DALs methods, first to retrieve the object main data (1) and one after that to get, only, the data of the tags related (2) so that your factory can fill-up the object's tags list:
(1)
SELECT * FROM dbObject WHERE Id=#objectId
(2)
SELECT t.* FROM dbTags t
INNER JOIN dbTag Connection c ON c.TagId = t.dbTagId
INNER JOIN dbObject p ON p.Id = c.PointId
WHERE p.Id=#objectId
If you have many objects and the amount of data is just a few (meaning that your are not going to manage big volumes) then I would look for a ORM based solution as the Entity Framework.
I (still) feel comfortable writing SQL queries in the DAOs to have under control all queries being sent to the DB server, but finally it is because in our situation is a need. I don't see any inconvenience on having to query the database to recover, first, the object data (SELECT * FROM dbObject WHERE ID=#myId) and fill the object instance, and then query again the DB to recover all satellite data that you may need (the Tags in your case).
You have be more concise about your scenario so that we can provide valuable recommendations for your particular scenario. Hope this is useful you you anyway.
We used stored procedures that returned multiple resultsets, in a similar situation in a previous project using Java/MSSQL server/Plain JDBC.
The stored procedure takes the ID corresponding to the object to be retrieved, return the row to build the primary object, followed by multiple records of each one-to-many relationship with the primary object. This allowed us to build the object in its entirety in a single database interaction.
Have you thought about using the entity framework? You would then interact with your database in the same way as you would interact with any other type of class in your application.
It's really simple to set up and you would create the relationships between your database tables in the entity designer - this will give you all the foreign keys you need to call related objects. If you have all your keys set up in the database then the entity designer will use these instead - creating all the objects is as simple as selecting 'Create model from database' and when you make changes to your database you simply right-click in your designer and choose 'update model from database'
The framework takes care of all the SQL for you - so you don't need to worry about that; in most cases..
A great starting place to get up and running with this would be here, and here
Once you have it all set up you can use LINQ to easily query the database.
You will find this a lot more efficient than going down the table adapter route (assuming that's what you're doing at the moment?)
Sorry if i missed something and you're already using this.. :)
As far I guess, your database exists already and you are familiar enough with SQL.
You might want to use a Micro ORM, like petapoco.
To use it, you have to write classes that matches the tables you have in the database (there are T4 generator to do this automatically with Visual Studio 2010), then you can write wrappers to create richer business objects (you can use the ValueInjecter to do it, it is the simpler I ever used), or you can use them as they are.
Petapoco handles insert / update operations, and it retrieves generated IDs automatically.
Because Petapoco handles multiple relationships too, it seems to fit your requirements.
Anybody know if it's possible to;
Dynamically create LINQ classes for tables/columns that change regularly?
If that creation can be used in DynamicData.
A web app we are developing creates tables and columns in SQL. We want to edit these tables in DynamicData.
Thoughts?
Depending on what type of Database you are running, but you could always have a linq statement that queries the systems schema table and have it return the tables and columns. Then could use what you return and then use another linq query to break out the information from each table.
I used sqlmetal.exe from the SDK, it's a winner.
Is this LINQ statment vulnerable to SQL injection?
var result = from b in context.tests
where b.id == inputTextBox.Text
select b;
where context is an Entity and tests is a table.
I'm trying to learn LINQ and I thought that the benefit of it was that it wasn't vulnerable to sql injection, but some stuff I've see has said differently. Would I need to parametrize this LINQ statement to make it safer? If so, How?
Also would this be considered linq to sql or linq to entities?
Short answer: LINQ is not vulnerable to SQL injection.
Long answer:
LINQ is not like SQL. There's a whole library behind the scenes that builds SQL from expression trees generated by compiler from your code, mapping the results to objects—and of course it takes care of making things safe on the way.
See LINQ to SQL FAQ:
Q. How is LINQ to SQL protected from
SQL-injection attacks?
A. SQL injection has been a significant risk for traditional SQL
queries formed by concatenating user
input. LINQ to SQL avoids such
injection by using SqlParameter in
queries. User input is turned into
parameter values. This approach
prevents malicious commands from being
used from customer input.
Internally, it means that when LINQ to SQL queries the database, instead of using plain values, it passes them as SQL parameters, which means they can never be treated as executable code by the database. This is also true for most (if not all) ORM mappers out there.
Compare these two approaches (totally pseudo-code):
string name = "' ; DROP DATABASE master --"
run ("SELECT * FROM Authors WHERE Name = '" + name + "'") // oops!
// now we'd better use parameters
SqlParameter name = new SqlParameter ("#name", "' ; DROP DATABASE master --")
run ("SELECT * FROM Authors WHERE Name = #name", name) // this is pretty safe
I suggest you dive deeper into what LINQ statements actually mean and when and how they get translated to the real SQL. You may want to learn about LINQ standard query operator translation, deferred execution, different LINQ providers et cetera. In case of LINQ, much like any abstraction technology, it is both fascinating and incredibly useful to know what's happening behind the scenes.
P.S. Everytime I see a question about SQL injection I can't help but remember this webcomic.
LINQ uses parameterized queries so it is not generally susceptible to SQL injection. Your example, for instance, isn't vulnerable.
The LINQ to Entities provider uses parametrized queries and is completely safe against SQL injection.
No. LINQ to Entities and LINQ to SQL handle the generation of SQL Queries to avoid SQL Injection. You can use LINQPad if you're curious to see what SQL statement gets generated when you run this query with various inputs.
Whether it's LINQ to SQL or LINQ to Entities depends on what your context object is, and cannot be determined from this code snippet.
The only time you need to worry about SQL injection in LINQ is if you're using the ExecuteQuery method to run a custom SQL query (see here). But at that point, you've moved away from the Language-INtegrated Query, and back into the world of generating your own strings.
LINQ To SQL generates a parameterised query so it protects against SQL injection attacks
Linq paramaterizes all queries, so isn't susceptible to SQL injection attacks. However you should still validate all of your user input as otherwise you will leave yourself open to cross site scripting attacks.
I am working on .aspx page that uses a t-sql query that uses a multivalued input parameter (a set of labnames) using an array that would store all the labnames prior to running the query.
I have the following parameters for the query.
With c.Parameters
.Add(New SqlParameter("#sdate", sdate.text))
.Add(New SqlParameter("#edate", edate.text))
.Add(New SqlParameter("#labname", SqlDbType.Text)).Value = labnamesparam.ToString
End With
However, I still see that only one labname (3rd param in the order).
Any ideas on this?
For SQL 2008 your should use a TVP, as recommended by Marc.
For SQL 2005 there are several techniques like using XML or using a comma delimitted list. A comprehensive analysis of each technique is kept by Erland Sommarskog on hi page at http://www.sommarskog.se/arrays-in-sql-2005.html.
For SQL 2000 the options are fewer, and again Erland has a comprehensive discussion of each at Arrays and Lists in SQL Server (SQL 2000 and Earlier).
I highly recommend Erland's articles, they've been the reference on the subject for many years now.
You need to turn the contest of the array into a string. Here is a c# example, certainly not the only way to do it.
System.Text.StringBuilder k = new System.Text.StringBuilder();
foreach (string x in LABNAMES) {
k.Append(x);
k.Append(",");
}
.Add(New SqlParameter("#labname", SqlDbType.Text)).Value =k.ToString();
Your going to have to change your sql though you can't have a dynamic in clause like that. Old trick but not good practice is to turn the whole sql into a string and do an execute one it.
You might have to do a little bit more work in your stored procedure if you want to pass along an array of strings to it and perform a T-SQL "IN" operation.
This article has a very good example.
IF you use SQL Server 2008, you could use the "table-valued parameter" (TVP) feature.
Basically, in SQL Server 2008, you need to define a user-defined table type:
CREATE TYPE Customer AS
TABLE (id int, CustomerName nvarchar(50), postcode nvarchar(50))
and then use that in your stored procedure as a parameter:
CREATE Procedure AddCustomers(#customer Customer READONLY)
And then in your C# code, you'd create a DataTable variable of the same structure, and use that as the input parameter. That way, you can pass in any number of values, and any structure you like.
See these excellent blog posts for more information and extensive code samples:
Guy Burstein
Ben Hall
SQL-Team
Marc