Oracle parameter with Dapper issue - c#

I am struggling with using ORACLE parameters via DAPPER. The error message received is "ORA-00942: table or view does not exist".
However the code works without the parameter, and I suspect that this is a simple Oracle parameter syntax issue. The code follows:
public List<ForecastData>GetByFiscalYear(string fiscalYear)
{
List<ForecastData> queryResults = new List<ForecastData>();
String sqlQuery = #"SELECT RES.FISCALYEAR year FROM RESOURCE_AVAILABILITY RES WHERE RES.FISCALYEAR = :p_fiscalYear";
using (var oraCon = new OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings["Oracle_HRZD"].ToString()))
{
oraCon.Open();
queryResults = oraCon.Query<ForecastData>(sqlQuery, new { p_fiscalYear = fiscalYear }).ToList();
}
return new List<ForecastData>(queryResults);
}
Any assistance will be greatly appreciated...

Usually, ORA-00942 is exactly what it says, it can't find the table/view (RESOURCE_AVAILABILITY) you are selecting from. So it's not in the schema for the user you log on as or the user has not been granted SELECT on the table/view if it's another schema.
But you say that if you remove WHERE RES.FISCAL_YEAR :p_fiscalyear, then it works. So it seems like you have select permissions on the table. Do you mean remove the whole where selection or have you tested enter a fixed string, as in WHERE RES.FISCAL_YEAR='2016'?
My other top tip is to run Wireshark and look at what really is sent to the database, usually you connect on port 1521 filter on that.

The answer was to use the fully-qualified database-object name, including the schema. Thanks for your assistance.

Related

Linq to SQL not saving to database on SubmitChanges()

I have a database with three tables in it. I created all the tables within Visual Studio. My C# code is connecting to the database using Linq to SQL. The table I am having problems with is not updating on SubmitChanges().
using (DataClasses1DataContext db = new DataClasses1DataContext())
{
tbl_Inventoryv2 inv = new tbl_Inventoryv2();
inv.Title = addTitleTextBox.Text;
inv.Model = addModelTextBox.Text;
inv.Category = addCategoryTextBox.Text;
inv.Quantity = int.Parse(addQuantityTextBox.Text);
inv.Price = decimal.Parse(addPriceTextBox.Text);
inv.Description = addDescriptionTextBox.Text;
db.tbl_Inventoryv2s.InsertOnSubmit(inv);
db.SubmitChanges();
int id = inv.IdInventory;
MessageBox.Show($"Item creation successful. Item number is {id}");
}
My database does have a primary key called IdInventory that is set to increment. Within the program, the correct increments are working as shown in my MessageBox statement above, but it never actually gets saved to the database. I have also checked the properties of the database file in Visual Studio and the path to the database is correct, as well as the Copy to Output Directory is set to Copy if Newer. Most of the questions I have looked up indicate that is usually the problem, but that doesn't look like the case for me. I am new to SQL and interacting with it via Visual Studio/c#, and SQL in general, so any input is greatly appreciated.

SqlDependency not working with Existing Database

I'm using Signalr with SqlDependency. My code works and it shows me realtime results like I wanted. But the issue is it is working my newly created database. If I change the database to old one the SqlDependency stops work and not getting the change detection on my database table.
Below is my code:
#region SignalRMethods
[System.Web.Script.Services.ScriptMethod()]
[System.Web.Services.WebMethod(EnableSession = true)]
public GlobalApplicationError[] GetErrorsList()
{
var cs = "Data Source=.;Initial Catalog=NotifyDB;Integrated Security=True";
using (var connection = new SqlConnection(cs))
{
connection.Open();
SqlDependency.Start(cs);
using (SqlCommand command = new SqlCommand(#"SELECT [Form_Name],[Message],[Prepared_By_Date] FROM [GlobalApplicationError]", connection))
{
// Make sure the command object does not already have
// a notification object associated with it.
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
using (var reader = command.ExecuteReader())
return reader.Cast<IDataRecord>()
.Select(x => new GlobalApplicationError()
{
Form_Name = x["Form_Name"].ToString(),
Message = x["Message"].ToString(),
Prepared_By_Date = Convert.ToDateTime(x["Prepared_By_Date"])
}).ToList().ToArray();
}
}
}
private static void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
MyHub.Show();
}
#endregion
Above code perfectly works on database NotifyDB but not on my existing one which is eprocure if I change the database in my connection string. As I'm using the asmx web service so I always update the reference of my web service. Plus I've enable_broker set to true on both databases.
Database screen shots:
NotifyDB
eprocure
output
Kindly let me know what I'm doing wrong in my code. Thanks in advance.
Let windup this. After some brainstorming on internet I successfully found my answer.
I've Checked my database sys.transmission_queue using below query:
select * from sys.transmission_queue
As most likely our notification(s) will be there, retained because they cannot be delivered. The transmission_status have an explanation why is this happening.
I found that there is below error:
Error: 15517, State: 1. Cannot execute as the database principal because the principal "dbo" does not exist
Google it and found the below useful link:
Troubleshooting SQL Server Error 15517
after that I run the below query which is briefly defined in above link
EXEC sp_MSForEachDB
'SELECT ''?'' AS ''DBName'', sp.name AS ''dbo_login'', o.name AS ''sysdb_login''
FROM ?.sys.database_principals dp
LEFT JOIN master.sys.server_principals sp
ON dp.sid = sp.sid
LEFT JOIN master.sys.databases d
ON DB_ID(''?'') = d.database_id
LEFT JOIN master.sys.server_principals o
ON d.owner_sid = o.sid
WHERE dp.name = ''dbo'';';
By doing this, I found several databases that sys.databases said had an owner. However, when I checked it from the database's sys.database_principals, the SID didn't match up for dbo. The column I had for dbo_login came back NULL. That was a clear sign of the issue. There is also the possibility you will see a mismatch between dbo_login and sysdb_login. It appears that as long as dbo_login matches a legitimate login, the error is not generated. I found that on some DBs on one of my servers. While it's not causing a problem now, I'll be looking to correct the mismatch.
Correcting the Error:
The easiest way to correct the error is to use ALTER AUTHORIZATION on the databases which have the NULL login match for dbo. It's as simple as:
ALTER AUTHORIZATION ON DATABASE::eprocure TO sa;
So finally. I got what I want and my SQL Dependency is working fine. This is all from my end. Thanks you help me on this post. I appreciate for your precious time. Happy Coding.
Please make sure Query Notifications & Service broker are enabled and permissions for the IIS identify are granted.
Steps to enable : https://techbrij.com/database-change-notifications-asp-net-signalr-sqldependency
To check service broker is enabled execute the below statement
SELECT name, is_broker_enabled FROM sys.databases
To enable service broker
ALTER DATABASE <<DatabaseName>> SET ENABLE_BROKER
To grant permission to a user
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO “<<USERIDENTITY>”

c# using a binding source to add row to an sql table with incremental identity field

I have a program I created in Visual studio. The program is basically a place for everyone to store passwords for company and external accounts. I want to further this application by automatically creating the company accounts when I create a new user. I approached this by using the binding source. I can get the row into the database but it doesn't use the sql supplied auto increment. I will post the code but I am trying to figure out if I went about this the wrong way. I am not 100% familiar with how the connector and classes that visual studio create when you connect the solution to the database. I am not looking for code to help me do this I am looking for explanations and guidance. If responding with code please help me understand by explaining the code.
DataSet.AccountsRow newdomainuserrow = DBDataSet.Accounts.NewAccountsRow();
newdomainuserrow.USer = userIDTextBox.Text.ToString();
newdomainuserrow.UserName = userIDTextBox.Text.ToString();
System.DateTime moment = new DateTime();
newdomainuserrow.Password = moment.Year;
newdomainuserrow.AccountName = "Domain";
drawingNumDBDataSet.Accounts.Rows.Add(newdomainuserrow);
MessageBox.Show("User Saved");
this.Validate();
this.usersBindingSource.EndEdit();
this.accountBindingSource.Endedit();
this.tableAdapterManager.UpdateAll(this.DataSet);
All help is greatly appreciated.
Matt
I found a solution. The id field is not longer an identity autoincrement field. To increment the id field one by one programmatically like I need to I wrote a simply while statement to get all numbers that were not used. This works if there is a deleted row it will insert one where there is one missing. here is the code I used.
Boolean gotnum;
gotnum = false;
int idnum = 1;
while (gotnum != true)
{
DrawingNumDBDataSet.AccountsRow actrw = drawingNumDBDataSet.Accounts.FindById(idnum);
idnum++;
if (actrw==null)
{
gotnum = true;
idnum--;
}
}
I then set the Id field = to idnum. This is probably not the best practice but it is the best I could come up with.

view SqlXmlCommand.ExecuteCommand() on SQL server

I am having an issue where I am looking at a legacy application that is using SqlXmlCommand objects to get data from the database. There is an .xsd file that has the tables that are being used, and what fields, their relationships etc. The issue that we are having is it works most of the time, but not all. I am wondering if there is a way to check what is actually being run on Sql Server. I don't have the SQL profiler installed so that option is out.
the code looks like:
SqlXmlCommand xcmd = new SqlXmlCommand(DataAccess.OleDbConnectionString);
xcmd.CommandType = SqlXmlCommandType.XPath;
xcmd.SchemaPath = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"myXsd.xsd"));
xcmd.XslPath = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, String.Format(#"myXsl.xsl", ReportType)));
xcmd.CommandText = "id[#PK=$PK]";
SqlXmlParameter p = xcmd.CreateParameter();
p.Name = "#PK";
p.Value = Id;
using (Stream s = xcmd.ExecuteStream()) { ... }
This blows up at the ExectureStream() with the error:
SQLXML: error loading XML result (XML document must have a top level element.)
We believe that there is some data abnormality that is causing the xml to not generate properly, and that is why we want to see what is exactly run.
Cheers
You can try the below two queries, you might need to tweak it a little, but to give you an idea, the first gives you a list of all requests, and the second will give you the detail of the request by its request id (session_id)
SELECT *
FROM sys.dm_exec_requests
DBCC INPUTBUFFER (12345)
Although I would personally rather try and debug the C# app first and view what's being sent over to the server from the VS debugger before bothering with checking what's being run on SQL Server
Also, DBCC INPUTBUFFER might give you something like EXECUTE dbo.MyStoredProc 'params...', to dig deeper, or otherwise a more straightforward query, you can run this
SELECT r.session_id, r.[status], r.command, t.[text]
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.[sql_handle]) t

Crystal Reports and Login issue

I need some help.
Actually, I've read about this problem, and I thought that I've resolved it, but it keeps bothering me.
It's about different logins at developing and production enviroment.
This was supposed to be solution (EF and SQL Server):
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder((model.Connection as EntityConnection).StoreConnection.ConnectionString);
ConnectionInfo ci = new ConnectionInfo();
ci.ServerName = builder.DataSource;
ci.DatabaseName = builder.InitialCatalog;
ci.UserID = builder.UserID;
ci.Password = builder.Password;
report.SetDatabaseLogon(ci.UserID, ci.Password, builder.DataSource, ci.DatabaseName);
foreach (CrystalDecisions.CrystalReports.Engine.Table tbl in report.Database.Tables)
{
TableLogOnInfo logon = tbl.LogOnInfo;
logon.ConnectionInfo = ci;
tbl.ApplyLogOnInfo(logon);
}
I extract login information from Entity Connection and apply it to all the tables in report. That should do the trick. I added SetDatabaseLogon() only to be sure, but that's not required.
Now, when I run report in production enviroment, report pops up a Database login screen showing CORRECT server name (production server), NOTHING next to database (that is my concern), proper username, and no password, asking to type in login information.
I type it in, but CR says "Login failed. Please try again". I mean WTF. I use the very same credential to connect to database with Management Studio.
I am using WPF viewer, BTW.
I am really stuck here, I've done some debugging, and connection info gets all the right data, so it must be report who is the culprit, but what should I do?
Any help would be appreciated. I hope somebody has stumbled to a same problem before me.
Regards
I had a problem with using "SetDatabaseLogon"
I changed by
report.DataSourceConnections[0].SetConnection("Servername","InitialCatalog", "UserID", "Password");
I hope this will helpful to someone.
Looking at the code on my Blog Post that does the same jobs, I can see a few differences:
Set tbl.Location to itself (this might be re initializing something internally - it didn't work without it).
Put your code in a method that you can re-call to handle sub reports:
My version never needs to call report.SetDatabaseLogon
Other than that they're basically identical.
Code:
void SetConnection(ReportDocument rd, crConnectionInfo ci)
{
foreach (CrystalDecisions.CrystalReports.Engine.Table tbl in rd.Database.Tables)
{
TableLogOnInfo logon = tbl.LogOnInfo;
logon.ConnectionInfo = ci;
tbl.ApplyLogOnInfo(logon);
tbl.Location = tbl.Location;
}
if (!rd.IsSubReport) {
foreach {ReportDocument sd in rd.SubReports) {
SetConnection(sd,ci)
}
}
}
(Note: Just hand coded this, so check it before you use it).
This works on the VS2008 version of crystal reports (forget what it was called).
EDIT: One other thing, in my connection initialization, there are a couple of extra properties set:
ci.Type = ConnectionInfoType.SQL;
ci.IntegratedSecurity = false;
It was totally stupid problem, and i solved it by chance. Installation of Crystal Reports on my desktop computer was crooked or something, so whenever I edited something with database expert (add some tables, for example), it spoiled my report. All I did is use "set database location" option on my laptop, and now my reports run flawlessly.

Categories