I have created this stored procedure in a collection in my DocumentDb Account.
https://github.com/Azure/azure-documentdb-js-server/blob/a7a2db8c4abc6ce61d40e08b66358f03fd89f896/samples/stored-procedures/update.js
I am having trouble executing this with the .NET SDK, here is my code.
dynamic[] procParams = new dynamic[] { "myid", "{ $set: { status : 'Draft' } }" };
return await _client.ExecuteStoredProcedureAsync<Listing>(UriFactory.CreateStoredProcedureUri("dbName", "collection", "update"), procParams);
The SDK throws an ArgumentException:
"Cannot Serialize object if it is not document or attachment"
Seems like I can only pass Document's or Attachments which doesn't seem right?
I came across this blog post and it looks like this guy is doing the same but with no issues.
So how do I pass basic parameters to a stored procedure such as strings?
To clarify - it looks like that the exception above refers to an issue with de-serializing the stored procedure's response in to the Listing class (as opposed to referring to serializing the input parameter before executing the stored procedure).
You can verify whether this is true by examining the response of the stored procedure as a string:
var sprocResponse = client.ExecuteStoredProcedureAsync<string>(UriFactory.CreateStoredProcedureUri("dbName", "collection", "update"), procParams).Result.Response.ToString();
If you are able to retrieve the updated document response as a string; than that means the stored procedure successfully executed and should confirm the issue lies with de-serializing the stored procedure response in to the Listing class.
A common mistake here is for POCOs to extend the Document class (as opposed to the Resource class: Microsoft.Azure.Documents.Resource). Please make sure Listing does not extend Document, and that the response from the stored procedure can be de-serialized to the Listing class.
Related
Due to a huge and hateful database that I'm not allowed to rationalise, I am forced to create a C# Datalayer generator for my app. I'm pretty much done, using T4 to generate Model classes and Insight.Database repos but I needed to create my User Defined Table Types and Stored Procedures via Sql Management Objects.
What I'm interested in is, can I use a short-circuit parameter when creating via SMO? What I want to replicate is something like this:
CREATE PROCEDURE [dbo].[cip_GetLicenses]
#fldIndex int = null
AS
SELECT [fldIndex]
,[fldLicenceData]
FROM [dbo].[tblLicences]
WHERE (#fldIndex is NULL OR (fldIndex = #fldIndex))
I can construct the body of the sproc relatively easily with a string builder and some column iteration, but creating a parameter is done separately.
The StoredProcedureParameter Type does actually have a DefaultValue property but it's a string, and sadly setting it to " = null" simply throws exceptions at run time.
Can anyone advise?
How can I execute stored procedures generically? I tried:
_context.Set<TEntity>();
I want to avoid embedded SQL such as:
context.Database.SqlQuery<TEntity>(storedProcedureName);
However, because the stored procedure is accessed via a Function rather than a Type this does not work. I also tried creating/accessing via a function mapping. The complex type for the return result exists, but this can't be used to obtain the result itself.
Do I need Delegates or is there support for this somewhere?
To be clear, I hope to create something like....
public IEnumerable<TEntityResult> ReadSpAll<TEntity,TEntityResult>(IEnumerable<SqlParameter> sqlParameters)
where TEntity is the stored proc and TEntityResult is the complex return type
See "Using Import Functions to Map Stored Procedures"
# http://msdn.microsoft.com/en-us/data/gg699321.aspx
for code like
var context = new AWEntities();
ObjectResult<OrderDetail> orderDetailEnumerable = context.GetDetailsForOrder(71796);
List<OrderDetail> details = orderDetailEnumerable.ToList();
I wondering why it throws a error whenever i not intended to give name of datable.As we know there are constructor for datable class is overloaded.so If i using parameter less constructor is give the error by the basis of serialization .
Can Someone Explain Me why to use Parametrized one but not default for DataTable .
It's because the name is required for the data table to serialize properly.
Why is this? Well, the exact reason seems to be that the serialization process uses the table name as a key, and specifically, an empty data set is created to import it back in. When the name is not present, the part that looks for the table name throws an exception and this is why you see the error you are getting.
You don't have to use the constructor, though, you can set the TableName outside:
DataTable myTable = new DataTable();
myTable.TableName = "PleaseDontKillMySerialization";
If you are interested, you can look at the contents of the class using ILSpy. This way you can see for yourself how the class is created and look at how serialization works for this class.
As Marc mentions, though, using DataTable restricts you to .Net clients only. It's also quite a large object when serialized so more data has to be transferred per request.
I'm writing stored procedures in C# at the moment and I've run into a problem with the size of a parameter.
So I've created a project in VS 2008 and created several stored procedures which all look a bit like this:
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void SaveProgress(... SqlString logpart, ...)
{
...stuff...
}
}
Now because I've not specified anything else, when I deploy this to a database, the CREATE DATABASE statement (apparently) gets created with a nvarchar(4000) as the definition for the input parameter.
However, I regularly have to flush log parts larger than 4000 chars, so I'd like that to be nvarchar(MAX).
Now I think I can do some jiggery-pokery and use Management Studio to re-define the CREATE DATABASE statment, but I'd actually like to define the fact that I want it to be MAX in the project/solution, so the deployment gets done correctly and I don't have to start adding large wads of comments and/or documentation for anyone who needs to maintain this code after me.
Is there any way to specify this in the code or maybe in the AssemblyInfo or something like that?
Revisiting this years later, I tried to use SqlChars in a function that read data from the database and returned a formatted string with data in it. Using SqlChars actually made the function bomb, stating that it could not find linked server System - an error message that seems to have nothing to do with the problem, as I was never referencing a linked server in the first place.
Changing the return type and parameters back to SqlString, adding [return:SqlFacet(MaxSize = -1)] attribute to the function, and adding [SqlFacet(MaxSize = -1)] to each parameter made my function work properly.
Try using SqlChars. SqlChars automatically maps to NVARCHAR(MAX)
We are deploying multiple projects in C# with Oracle databases behind. I would like to implement all of the database logic in Oracle stored procedures as this
keeps all of the database logic in the database
makes it easier to maintain when database structures change
allows re-use of the stored procedures more easily across programming languages
I have test code running where I return rows using a SYS_REFCURSOR and I manually do the data bind on the results as SYS_REFCURSOR could be returning anything - i.e. its not type safe
My question is - is there any way I can define correct types in the stored procedure return type and correctly bind to that type safely in my C# code?
e.g. my PL/SQL procedure looks like this - the return part is not type safe - it could be anything. If I wanted to re-use it from another Oracle package then it will not have the correct type checking
PROCEDURE get_risk (p_process_id IN NUMBER, p_risk OUT sys_refcursor);
and my C# code looks something like the following. I have cludged this together from several classes so hopefully it makes sense. When I extract the data from the DB call I am manually defining the data types - I need to know in the C# code what the Oracle data types are
// setup procedure call
_oracleCommand = new OracleCommand("risk_pkg.get_risk", _conn.OracleConnection);
_oracleCommand.Parameters.Add(new OracleParameter("p_process_id", OracleDbType.Int64, processId, ParameterDirection.Input));
_oracleCommand.Parameters.Add(new OracleParameter("p_risk", OracleDbType.RefCursor, null, ParameterDirection.Output));
_oracleDataAdapter = new OracleDataAdapter(_oracleCommand);
_dataSet = new DataSet();
// call Oracle
_oracleDataAdapter.Fill(_dataSet);
// extract data - hand coded binding
Int64 dbRiskId = (Int64)_dataSet.Tables[0].Rows[0][_dataSet.Tables[0].Columns["risk_id"]];
Int64 dbClientId = (Int64)_dataSet.Tables[0].Rows[0][_dataSet.Tables[0].Columns["client_id"]];
return new Risk(dbRiskId, dbClientId);
This isn't necessarily a problem - I just want to know if there is a better way of doing this to make my PL/SQL more obvious in what it is returning, and making my C# code not have to know the Oracle data types - encapsulating me from database structure changes
Accepted solution : this seems to be the practical solution. I'm still slightly unsatisfied that my Oracle procedure isn't defining its return type explicitly, but that life
(You should post a sample of your to test code. Because I'm not sure, if I understand your question correctly.)
The returned type is Object to serve any possible return value. You have to convert it manually. But you could generate the code for the conversions. Define a table or a file with this meta information: which stored procedure returns which types and in which .Net types they shall be converted. Use this meta information to create the C# code.
We fill our RefCursors into a DataTable. The code to assign the table fields to their appropriate member variables is generated out of our meta tables.
I have used T4 text templating to do this with SQL server. Works incredibly well.