Calling a Sybase SP, error "SP not found" - c#

I am connecting to a Sybase 9 database to retrieve data. I can query the database without issue using ODBC connections but I am having an issue calling stored procedures. The procedure was written probably 6-7 years ago. This is what I have to execute the stored procedure.
OdbcCommand itemWeightAve = conn.CreateCommand();
itemWeightAve.CommandText = "ComputeLastCost";
itemWeightAve.CommandType = CommandType.StoredProcedure;
itemWeightAve.Parameters.AddWithValue("#OwnerId", "BananaHammock");//company number
itemWeightAve.Parameters.AddWithValue("#InventoryId", InventoryNumberHere);//inventory id from query results
itemWeightAve.Parameters.AddWithValue("#EndDate", EndDateHere);//end date from query results
OdbcDataReader itemAveReader = itemWeightAve.ExecuteReader();
I am not very familiar with Sybase or ODBC and the version these guys are using is extremely old and is no longer officially supported. Upgrading the Sybase database is out of the question. The error I get when attempting to execute this command is...
ERROR [42S02] [Sybase][ODBC Driver][Adaptive Server Anywhere]
Procedure 'ComputeLastCost' not found
I know that the procedure exists, it is typed correctly, and that the parameter names exist and are typed correctly. Does anyone have any tips/hints/suggestions for what I'm doing wrong here?

Turned the comment into an answer...
What is the default database of the login that you are using?
Is the stored procedure in the same database?
If not, you need to prefix your procedure name with the database name "sharedDB.ComputeLastCost".
You can check this by logging in with the same user/password through isql and try and exec it by hand. if you have to do a use database (ie. use database sharedDB) before you execute it, you need to put the db name in front.
You can also change your default database for the user. Either way should work.

Related

C# SQL Library is modifying my queries to fully qualified tables

It is changing my queries and appears to be fully qualifying my tables without me explicitly telling it to. Is there a way to stop it from doing that?
Here is the pertinent information as I see it. Let me know if anything else would be helpful.
We had a SQL Server named serverName. It's been in production for years. It was migrated away from a Windows 2008 Server to a Windows 2012 Server. The new server's name is sql_1234_4321 (not the real name but as terrible)
We have nth number of applications that were hitting the old serverName SQL Server so we took the old server offline and created a DNS entry for serverName that points at the new sql_1234_4321 hoping we wouldn't have to hit the connection strings for all the apps that were hitting the old server.
This worked for the most part except for some C# ASP.NET MVC apps.
They are using System.Data.SqlClient.SqlCommand.
Connection string:
Data Source=serverName;Initial Catalog=USData; Persist Security Info=True; User ID=appUn;Password=appPw
SQL query:
select FirstName from Customers
Code:
using (SqlCommand cmd = new SqlCommand(query, sqlConnection))
{
if (parameters != null)
{
cmd.Parameters.AddRange(parameters.ToArray());
}
var reader = cmd.ExecuteReader();
var results = new List<TType>();
while (reader.Read())
{
results.Add(convert(reader));
}
return results;
}
I get an error:
Could not find server 'serverName' in sys.servers.Verify that the correct server name was specified. If necessary, execute the stored procedure sp_addlinkedserver to add the server to sys.servers.
Why this error? The only time serverName is referenced is in the connection string. My query should just use default namespaces once its on the server. But it appears that my query is being fully qualified at some point in the process as the following:
select FirstName from serverName.USData.dbo.Customers
I added a linked server serverName on the new sql_1234_4321 server that just points back to itself and this seemed to fix the problem. However, this feels absolutely dirty and makes me wonder if it REALLY is doing a cross server query at that point or if its smart enough to say "HEY! we are hitting ourself so don't worry about going out to the network and making this more expensive than it should be" but i doubt it.
I thought about using synonyms but the problem is we have tables with the server name in them. And there may be queries hitting the server with the server name in them so the following would not work:
CREATE SYNONYM serverName FOR sql_1234_4321;
So then it would make sense that I'd have to make a specific synonym for each database on the server:
CREATE SYNONYM serverName.database1 FOR sql_1234_4321.database1;
CREATE SYNONYM serverName.database2 FOR sql_1234_4321.database2;
CREATE SYNONYM serverName.database3 FOR sql_1234_4321.database3;
CREATE SYNONYM serverName.database4 FOR sql_1234_4321.database4;
CREATE SYNONYM serverName.database5 FOR sql_1234_4321.database5;
CREATE SYNONYM serverName.database6 FOR sql_1234_4321.database6;
CREATE SYNONYM serverName.database7 FOR sql_1234_4321.database7;
CREATE SYNONYM serverName.database8 FOR sql_1234_4321.database8;
CREATE SYNONYM serverName.database9 FOR sql_1234_4321.database9;
CREATE SYNONYM serverName.database10 FOR sql_1234_4321.database10;
As you can see, this would be a nightmare to maintain and besides that feels super dirty.
My question is this... At what point is the table name being fully qualified out based on the connection string? Is there a way to prevent that from happening?
David Browne led me to find the issue. My query actually had a view referenced and the view had the reference to the old server. Huge oversight on my part to not notice that. Thanks David

Get name of "parent" database from assembly

I have a SQL CLR stored procedure written in c# (.NET4). Its purpose is to allow a trigger on a table in a SQL Server 2012 database to call a web service which then processes the data in that table.
However, there are several different databases which will all have triggers using this assembly. My web service needs to know which database is triggered the call to it in order to know where to get the data from.
I could simply add a parameter to my stored procedure but I want to keep things simple from the database side. Is there any way, in .NET, to obtain information about the database to which the assembly is attached?
Aah, found one:
This still opens a context connection to the database, but it's about the only way I can see.
using (SqlConnection conn = new SqlConnection("context connection=true"))
{
conn.Open();
string dbName = conn.Database
}
That's from an MSDN article. Also, the MSDN article on Context Connection.

Creating MySql Database on new install of c# application if it doesnt exist

I am about to deploy my application and have came into a bit of trouble.
I have the connection string for the database held in the application.settings and need a way to check if the database exists when the program first starts up, and if it doesn't, i need the program to create it before starting the program.
I am assuming it would be a mysql statement to check if db exists, if not create. However, I don't know where or how to do this, can I create a mysql dump of a blank database with tables etc already created and use that?
I have already stored the mysql dll files locally so there is no problem with that, its just creating the database that the string wants to connect to before the application runs so there are no connection errors straight away.
Thanks.
You can do this by running the following SQL statement:
SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = "my_db"
If it doesn't exist from the result set you get returned you can then create it.
This does pose questions regarding MySQL permissions and if your application should have user rights that enable such checking.
Edit in response of comments.
It isn’t clear if you create the connection string or not – I’ll assume the worst and that it is a part of the setup so your client can enter it (if you do know it the process below simplifies.
I would pass the connection string to the constructor of the MySqlConnectionStringBuilder class, this then makes it easy to connect to the database using the MySqlConnection class. I would use the properties from the new instance of the MySqlConnectionStringBuilder class (Server, Host, User etc) to setup the MySqlConnection class.
If the connection didn’t work I would return information to the user and they can update their connection string.
Once I’ve successfully connected to the database I would then use the database name from the Database property of my MySqlConnectionStringBuilder instance to build the query above.
If the command returns NULL the database doesn't exist and then needs creating, if the database does exist then the command will return the name of the database.
Now there are two paths:
It Doesn't exist – It needs creating, I would probably have an external SQL file with the create statements in (can be produced by MySQL dump by using the –nodata option). I would parse this file and execute the create statements
It does exist – I would now check the structure of the database to make sure it is compatible before continuing the installation.

Create SQL Server database from C# - using parameters

I am trying to put up a code to create a databases from my C# code (asp.net website).
This is my code:
SqlCommand myCommand = new SqlCommand("CREATE DATABASE #dbname", nn);
myCommand.Parameters.Add("dbname", dbname);
myCommand.ExecuteNonQuery();
nn.Close();
well, its not working. its giving me an error:
incorrect syntax near '#dbname'
BUT. if I won't use parameters, people can SQL inj to my database. do you have any idea how can use anything, to get the database name from a textbox. and that people can't SQL inj me database?
You can't use parameters in CREATE DATABASE or other DDL commands.
I'd suggest using SQL Server Management Objects instead of SQL

Stored Procedure doesn't exist, or does it?

I'm having a problem:
I have a db connection where I run stored procedures on. This same connection is used to create said stored procedures earlier on.
When I attempt to call a given stored procedure, later on, I get the following message:
Could not find stored procedure
'dbo.yaf_prov_upgrade'.
The problem is it actually does exist on the database. And there's also the fact that it shows up on the SQL Server Profiler.
RPC:Completed exec
[dbo].[yaf_prov_upgrade]
#PreviousVersion=46,#NewVersion=46 .Net
SqlClient Data
Provider Nico Matrix\Nico
I was wondering what could be the causes a particular query would throw such an exception even when it exists, it's called, and the call reaches the database.
It can't be a problem with the connection because it already executed other stored procedures. It can't be a problem with the procedure because it does exist, in fact the very same application, the very same web page, created it and put it there.
Update: forgot to mention I'm used integrated security, and I did run the SP on the database with the same user the application connects with, and I had no problem running it.
So what can it be?
Your RPC completed only means that the batch submitted to SQL Server was correct and completed. It doesn't mean the stored procedure ran and executed OK.
It will be (don't argue, check) one of:
wrong permissions
wrong database context
wrong server
stored proc is in a different database
To ensure that things are the same
SELECT
##SERVERNAME,
SUSER_SNAME(),
DB_NAME(),
USER_NAME(),
OBJECT_ID('dbo.yaf_prov_upgrade')
The OBJECT_ID will be NULL if the stored proc doesn't exist in that database or you don't have permissions.
I suspect it might be a permissions issue, check up if the user name your program is executing under has execute rights to the stored proc.
I'm no expert by far on ms-sql, but I do know it keeps SPs in a global cache. Is it possible the local connection only gets the global list of SPs upon connection? Maybe reinit the connection or re-select the cache?

Categories