How to retrieve multiple rows from a stored procedure with Linq to SQL? - sql

I've recently started to work with Linq to SQL and wondered how to get multiple rows as a result of executing a stored procedure,here's a simple sp i want to work with:
CREATE PROCEDURE gsp_ftsmultiple
#SearchKey varchar(100)
AS
BEGIN
SET NOCOUNT ON;
SELECT Label, theContent
FROM FtsTest
WHERE FREETEXT( theContent, #SearchKey )
END
Executing this sp from management studio is fine,but the corresponding method in the generated context class returns a int value, and I don't know how to get the actual rows, tried using the OUT parameters, but they can return only one result.

I think all you need to do is make a class that matches your result schema and make sure the function in the dbml has it as a return type.
see here on msdn

Try creating the fulltext predicates as wrapper functions instead of sprocs, like this. Worked for me.

When sqlmetal generates the code for this procedure, it doesn't pass a valid argument for the query to work.
Try to put something like this on the top of you SP:
IF #SearchKey IS NULL OR LEN(#SearchKey) = 0
BEGIN
SELECT N'' AS Label, N'' AS theContent WHERE 1 = 0
END
[...]
It will now deduce that 2 NVARCHAR columns are the usual output and generate code accordingly
PS. Code off my head, untested
Mike

I tested the following code snippet and it worked fine. If you put the generated code here, I can take a look and check where is the problem. Anyway, you can create a partial class as same name as your generated data context class and add the desired method manually as follows.
public partial class FooDataContext: System.Data.Linq.DataContext
{
[System.Data.Linq.Mapping.Function(Name = "GetFoo")]
public System.Data.Linq.ISingleResult<Foo> GetFoo()
{
System.Data.Linq.IExecuteResult res = base.ExecuteMethodCall(this, (System.Reflection.MethodInfo)System.Reflection.MethodInfo.GetCurrentMethod());
return (System.Data.Linq.ISingleResult<Foo>)res.ReturnValue;
}
}

You'd might be better off just running the query in itself, seeing as you're not really doing anything that requires a procedure. Just make sure you escape the search key properly.

Related

In Dynamic SQL, ScriptDom is finding IF statements, but not UPDATE statements

I'm using TransactSQL.ScriptDom to parse SQL statements. I have rules defined where I want to find a) IF statements and b) UPDATE statements. When I'm looking through non-dynamic SQL, the rules work just fine. However, when I'm looking through dynamic SQL, my code only detects the IF blocks; it does not detect the UPDATE statements.
For instance, this code gets hit in a debugger in both the non-dynamic and dynamic scenarios:
public override void Visit(IfStatement ifStatement)
{
...
}
However, this code does not get hit in any dynamic SQL scenario, and I've also tried using UpdateSpecification:
public override void Visit(UpdateStatement updateStatement)
{
...
}
Now, if I change the code to Visit(TSqlFragment test), the code will get hit, but I only see a node of type AsciiStringLiteral for my UPDATE statement. Is there a better way to get my code to visit an UPDATE statement?
Disregard, this was user error. I had a type-o in my dynamic SQL where I was incorrectly using single-quotes. In other words, I was using this:
#"EXEC('UPDATE dbo.MyTable
SET MyColumn = 'MyValue';');",
... instead of this:
#"EXEC('UPDATE dbo.MyTable
SET MyColumn = ''MyValue'';');",
(I considered deleting this question altogether, but I'll leave it up in case it helps others.)

Wha datatype is "System:VariableValue" in SSIS?

I need to log every change of variable values in a SSIS, at package level.
I have a SQL Task Editor that receives, as parameters, System::VariableName and System::VariableValue. I use this parameter to log a line in a DB log table.
Everything is working fine BUT... so far i only have numeric variables so, in the "Parameter Mapping", i specificed that the variable with name "System::VariableValue" is a NUMERIC DataType.
What happens when I will have a Datetime variable or a varchar variable? How can I handle variables of different types in this case?
Thankx
Make the datatype sql_variant, which will accommodate the different datatypes.
More on that here: https://msdn.microsoft.com/en-us/library/ms173829.aspx
Also, SSIS does have a on variable changed event which maybe helpful for you, though it sounds like you have a good custom solution.
m
EDIT:
So there is some documentation on MSDN that seems to suggest nvarchar maps to sql_variant. This worked for strings, but left the value empty for numeric values. Looking at the type for Variable.Value in the variables collection in a script task, it notes the type is empty. So I tried setting the data type to null, which did not work at all.
Finally, I created a script task to do the job and this worked correctly. The script task must call a stored proc in order for it to handle all the data types. I tested it with string, int, double and bool, all of which worked correctly.
Here is the table I used:
create table logging (myval sql_variant);
Here is the proc definition:
Create proc [dbo].[insertLog]
#myVal sql_variant
AS
Begin
set nocount on;
insert into logging values(#myVal);
end;
In the OnVariableValueChanged event handler, I added a script task with the following code:
using System.Data.OleDb;
public void Main()
{
// TODO: Add your code here
object val = Dts.Variables["System::VariableValue"].Value;
OleDbConnection conn = new OleDbConnection(Dts.Connections[".\\sql2016.Test"].ConnectionString);
using (conn)
{
conn.Open();
OleDbCommand cmd = new OleDbCommand("insertLog", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#myVal", val);
cmd.ExecuteNonQuery();
}
Dts.TaskResult = (int)ScriptResults.Success;
}
".\sql2016.Test" is the name of the connection manager in the package.
Please see if this will work for you,
m

Cannot implicitly convert type 'System.Data.DataTable' to 'RxPMIS.DSet01.tbSystemUsersDataTable'

Okay I may be asking this the wrong way, however simply put:
I am using tableAdapters in my dataset (DSet01) and have several Fill / Get data statements that I would like to eliminate by just passing on an SQL statement to populate the main dataset e.g. Main Table Adapter:= "tbSystemUsers" which has a general "Fill" "Get"...i.e. "Select * from tbSystemUsers" ... and instead of adding another query in this tableAdapter I want to create an SQL statement such as "Select * from tbSystemUsers WHERE (userId = #userID)".
And return the dataset which I can view on my data-grid.
I shouldn't have asked this question here: simply put the Project I inherited from a work colleague initially used a auto generated table adapters in its data-set designer. So this time around when i defined my classes, it fails because the GetData containers have already been define.
Either remove the table adapters class Or initialize my output to the same
existing one as in:
psmDS02.tbIssuesDataTable myIssues = new psmDS02.tbIssuesDataTable();
int postID = this.psmDS02.tbIssues[tbIssuesBindingSource.Position].issuesID;
myIssues = (psmDS02.tbIssuesDataTable) PsDataLayer.cls_0_gridsData.Issues_GetData_ID(postID);
The conversion is in the third line. Thanks

Call stored function without knowing the parameter names through vb.net

Can some one suggest me how to call a stored function in oracle through vb.net.
From vb.net should i able to pass the values to arguments of that function without knowing the parameter names?
Example: I have a function,
Create or Repalce Function Func_Name(param1 Varchar2,param2 varchar2)
Inorder to call this function through vb.net, we need to give
parameterargs.paramtername="param1"
Is there anyway so that i cannot use the parameter name and call the function
Thanks in advance
Rupesh
The way that we handled it was to open the Oracle DB up through an OleDbConnection, then call GetOleDbSchemaTable asking for the Procedure_Columns.
For example:
DataTable dtTable;
dtData = this.Connection.GetOleDbSchemaTable(OleDbSchemaGuid.Procedure_Columns, new object[] {null, null, sName, null});
foreach (DataRow theRow in dtData.Rows)
{
// Columns available in the row include:
// column_name, data_type, type_name, precision, and scale
}
Then, if you need to execute it without valid parameters (for example, to get the columns it exposes) you could execute it using DbNull.Value for each parameter.
Also, I can't remember exactly how Oracle operates, but in SQL Server you need to include the namespace when executing the function (i.e. select * from dbo.fn_my_test()). Also, depending on how the function is structured, you may have to select from it instead of executing it.
I'm not sure if you can use named parameters with Oracle.
When you create the parameterized query, try using question marks as a place holder:
Select col1, col2 From tablename Where col1 = ? and col2 = ?
Then, be sure to add the parameters to the command object in the correct order.
You don't need to know the parameter names to call it.
You need to know the number and type of them
Adding parameter names to the call means you don't have to pass all of them and / or you can pass them in a different order to the signature of the SP.
Call it like a parameterised query.
PSEUDOCODE
int customer_ID = 786;
Command.CommandText = 'Exec SP_MYProc #MyVar';
Command.Parameters.Add(new Parameter('MyVar',DbType.Int,customer_ID));
Command.Exec

NHibernate ISQLQuery SetParameter issue

This is probably fairly straightforward but i can't seem to find a reasonable explanation in any documentation.
I'm trying to use an NHibernate.ISQLQuery and using SetResultTransformer() to return a custom set of results from a custom SQL query. Like so:
public virtual IList<T> GetSQLObject<T>(string sql, IDbParameter[] parameters = null)
{
ISQLQuery qry = _sess.CreateSQLQuery(sql);
qry.SetResultTransformer(Transformers.AliasToBean(typeof(T)));
if (parameters != null) {
foreach (IDbParameter parameter in parameters) {
qry.SetParameter(parameter.Name, parameter.Value);
}
}
return qry.List<T>();
}
From looking at the examples, it seems that in the sql query I have to use parameters in the format :param1 instead of #param1 as I would in a standard SQL query. If i use the latter syntax in the query, it throws an error at qry.SetParameter().
Is there a reason why ISQLQuery/NHibernate requires them in this format and won't work with the normal syntax?
SQL Server uses #param, but not every other database does. For example, MySQL uses ?param
NHibernate allows you to swap out 1 database implementation for another with little to no reworking of your DAL. It sets the parameters based on the database you configured when you setup the NH Configuration.
Edit: Also I think :param came about from Hibernate being targeted at Oracle when it was initially developed, since Oracle uses :param
Phil has answered the "why"; so perhaps I can recommend a "how"; why not just add a new extension method to the IDbParameter type (something like .GetNHibernateName() ) that will return the parameter name with the "#" replaced with a ":"; that should be trivial to implement.