Output Linq Query Result to XML - c#

In the SQL Server Management studio, I can do this:
SELECT * FROM tableName FOR XML RAW
to produce a list of XML entries for the data in my table.
How do I do it in C# using LINQ queries?
var itemCollection = from entry in dataContextTableName select entry for xml raw
doesn't work (it doesn't compile). Any ideas?

You could write a stored procedure, return the XML as an OUTPUT parameter and access that through the LinqToSql DataContext.
For example:
CREATE PROCEDURE dbo.GenerateXML
(
#xmlOutput nvarchar(MAX) OUTPUT
)
AS
BEGIN
SET #xmlOutput = (
SELECT * FROM tableName FOR XML RAW
)
END
From here you'd have to drag and drop the stored procedure onto your DBML file using Server Explorer, then in code it's simply:
string xml = "";
dataContext.GenerateXML(ref xml)
The source on this can be found here
As James said, you can't do it using raw LinqToSql syntax; alternatively you could serialize the result you get from a standard Linq query (eg: from entry in dataContextTableName select entry) into XML in code, see here for a good starting point.

Related

Efficient approach of working with XML Payload node in SQL server from C# code

I working to find a match of a specific value from the C# code with the XML from SQL Server.
The data in SQL Server looks like this:
Payload looks like below
<?xml version="1.0"?>
<MyTransaction>
<Result>ResultValue</Result>
<ToCompare>ToCompareValue</ToCompare>
</MyTransaction>
Now, in C# code I have certain value for instance 'CSharpValueToCompare'.
For that, I need all the 'Result value' from the Payloads found in SQL Server
where ToCompareValue == CSharpValueToCompare
I am achieving this by using a stored procedure call which uses the cursor to open all the payloads and uses XPath query to compare the code and return the value if found.
Example code from stored procedure:
set #tPayloadXml = cast(#tPayload as Xml);
set #MyTransaction=#tPayloadXml.query('(MyTransaction/ToCompare = "CSharpValueToCompare"])');
set #result= #MyTransaction.value(' (ns:Result/text())[1]', 'varchar(64)');
Using a cursor on this will be highly inefficient and that is not preferred and also too slow and dumb process.
I would like to achieve this using the best methodology.
Also, I have worked using the same in the c# code by using the entities context and to load all the desired payloads and search in them. But this approach is a lot more inefficient as compared to the previous one as I am loading all of them in the code and using 1 only if found.
You can use .value to parse the xml directly in SQL.
eg:
declare #t table (payload xml)
insert #t (payload) values ('<?xml version="1.0"?><MyTransaction><Result>ResultValue</Result><ToCompare>ToCompareValue</ToCompare></MyTransaction>');
insert #t (payload) values ('<?xml version="1.0"?><MyTransaction><Result>ResultValue2</Result><ToCompare>CSharpValueToCompare</ToCompare></MyTransaction>');
select payload.value('(/MyTransaction/Result)[1]','varchar(64)')
from #t
where payload.value('(/MyTransaction/ToCompare)[1]','varchar(64)')='CSharpValueToCompare'

How to create a stored procedure with dynamically created IN set

I have some SQL that I am converting to stored procedures via blind requirement/request. There is a bit of SQL in the application I'm looking at that builds the where clause with a dynamic IN (set) statement. I have searched for dynamic stored procedure but nothing close to what I'm looking for has come up for me. Here is a sample of the WHERE clause:
WHERE Var.A = #Param AND Var.Id IN
From here the SQL is built manually using a string builder and then executed. Not sure how I'd convert this into a stored procedure as I'm fairly new to them.
We are using C# and SQL Server
You could use an user-defined data type.
On the C# side it would look like this:
//Setup a DataTable with the same structure as the SQL Type
var data = new DataTable();
data.Columns.Add("value", typeof(string));
//Populate the table
data.Rows.Add("oneID");
data.Rows.Add("anotherID");
//You create your sql command
cmd.Parameters.Add("#listArgument", data);
//Command execution
On the SQL side you could have a type like this
CREATE TYPE [dbo].[NVarCharTable] AS TABLE (
[value] NVARCHAR(MAX) NOT NULL);
And then the Stored procedure:
CREATE PROCEDURE [dbo].[MyProc]
#listArgument NVarCharTable READONLY
AS
BEGIN
SELECT *
FROM FOO
WHERE Var.Id IN (Select [value] FROM #listArgument)
END
Reference: https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/table-valued-parameters
If you are using SQl SERVER 2016 or above you can use the string_split function to convert the csv params into table and then use it in your IN list
e.g.
SELECT * FROM TBL WHERE Var.A = #Param AND Var.Id IN (SELECT value FROM STRING_SPLIT(#inlist, ','))
Hope this helps
To piggy back off of #lostmylogin, you can pass in a parameter delimited and use one of these SQL functions to parse it into a table:
http://sqlservercentral.com/scripts/SUBSTRING/124330
or
http://sqlservercentral.com/scripts/Miscellaneous/31913

Determine SQL Server query (stored procedure) result type

I am planning to organize my data in SQL Server as a small orm of my own, creating classes of meta data on each in my code.
For the tests I am hard-coding the objects, the next step is to generate the properties of each using SQL Server queries about those objects.
And now that I deal with the stored procedures section of my code in C#,
I was wondering how it is possible to somehow use SQL Server to query the result type of the command executed?
For example, here we know what it's doing even by reading its name ...
[dbo].[GtallDrLFilesCount]
but another could select some other type of return such as rowset string etc'
Using the above stored procedure will return an int :
if(#AllDrives=1) Begin
Select
* From [dbo].[HddFolderFiles]
End
but the next (above) selects all content rather the RowsCount
I was planning to access SQL Server and query it's objects, and as I do not plan to set return parameter (OUT), is there a more elegant way to achieve it, rather than parsing the .sql file of the stored procedure?
Like if text contains SELECT * (this is a rowset) expect it with DataTable
if text contains Select COUNT(*) (this is int) prepare int type variable.
I thought in the case I did not assign an out parameter to my stored procedures can SQL Server tell the return type somehow even though it has no out parameter to make it easy for it?
I think you would have to execute the SProc to get it's columns, but you could do it without actually returing data using set fmtonly
Even sprocs that return a single value (eg - int) return a table when you use c# ... so you just need to take a look at the reader's Columns to get the data you want.
So:
set fmtonly on
exec [dbo].[MyStoredProc] 0
set fmtonly off
Will return a recordset which you can examine in c#
var adoCon = new System.Data.SqlClient.SqlConnection(_sConnectStr);
var adoCmd = new System.Data.SqlClient.SqlCommand("your SQL (above)", adoCon);
var Rows = adoCmd.ExecuteReader();
DataTable dtSchema = Rows.GetSchemaTable();
Now - you can wander through dtSchema to get columns. It's not pure SQL, but it's a c# + SQL approach. [dbo].[GtallDrLFilesCount] will return a single column table (column of type int).
Obviously - use a SQL command (not string). The next trick is translating SQL types into native c# types (easy for some data types and tricky for others ... take a look at ADOCommand's ReturnProviderSpecificTypes option).
Hope that helps!
From SQL Server 2012+ you can use sys.dm_exec_describe_first_result_set to read metadata about resultset:
This dynamic management function takes a Transact-SQL statement as a
parameter and describes the metadata of the first result set for the
statement.
SELECT *
FROM sys.dm_exec_describe_first_result_set(
N'EXEC [dbo].[MyProcedure]', NULL, 0);
SELECT *
FROM sys.dm_exec_describe_first_result_set(
N'SELECT * FROM [dbo].[tab]', NULL, 0);
SqlFiddleDemo
This method has limitation for more info read Remarks section

PetaPoco stored procedure error "Incorrect syntax near the keyword 'FROM'."}

I'm using C# with TSQL and SQL Server 2005
I'm trying to use PetaPoco to return a dataset as a list of objects. this is the code I'm using just now
var s = PetaPoco.Sql.Builder.Append("USE [BI] EXEC [dbo].[TestProcedure2];");
var result = db.Query<dynamic>(s);
var result2 = db.Query<dynamic>("USE [BI] EXEC [dbo].[TestProcedure2];");
I think the error message is a generic sql error for when petaPoco fails.
At first I was using a stored procedure with paramaters and the # character was causing a problem, once that was fixed with ## i started getting this error so I made a stored procedure with a simple select statement. The procedure executes completely fine in Management Studio.
Using PetaPoco with select statements is fine and the data is mapped both to a dynamic or an object model completely fine. I created a garbage SQL string and it returned the same error which is where I'm getting the generic error idea from.
This is the select I'm using which works fine
var dynTest =
db.Query<dynamic>(
"SELECT TOP 10 * FROM [BI].[dbo].[Managers] ORDER BY [ConsecutiveDays] desc");
Its trying to append the select clause in front of it.
If you put a ";" at the start of your query it won't try to append it.
PetaPoco assumes that you want to perform a SELECT and will infer one if you don't include one.
To avoid doing the automatic SELECT you should use:
db.EnableAutoSelect = false;
Prior to your query.

Why linq fail to get temp table values

work on C# vs2008. I have a stored procedure ,This procedure holds temp table ,i need to get the temp table values.My sql query is bellow:
create procedure [dbo].[TestProcedure]
as
SELECT * INTO #temp1 from(select * from DischargePort) as b
select * from #temp1
drop table #temp1
My above query has a temp table named #temp1.After run this query in sql-server-management i get result ,but when i try to execute this procedure in linq ,I get no result.My linq syntax is bellow:
var r = ProviderName.TestProcedure();
Can anybody tell me why this problem arise,How to overcome this problem.Hope any body not say that linq can not handled the temp table or this kind of word.if have any query plz ask .Thanks in advance.
I don't think this is anything to do with the temporary table, but rather that Linq does not know what output is to expected.
With Dotnet Framework 4, this is easy, as you can do something like
(from r in ProviderName.TestProcedure().AsDynamic()
select new { r.Id, r.Description}).ToList()
(assumes Id and description are fields in DischargePort)
Otherwise, you need to do something in your designer to tell Linq what your procedure outputs. I have never had to do this, but perhaps this article will help.
When I think about it, in this particular case, you should be able to do something like
var results = (from r in ExecuteQuery<DischargePort>("exec TestProcedure")
select r ).ToList();
i would start by downloading linqpad to see the sql that linq is emitting, this may provide some clues. you could also use the sql profiler tool to see what query is being run.

Categories

Resources