My company is using SQL Server Compact to store and manage a local database and I need to get the primary key information from the database tables.
I have used OleDbConnection.GetSchema() in the past to get this information from Access databases using Jet and OLE drivers. But it appears that SqlCeConnection.GetSchema() throws a NotImplementedException (or rather that it returns DBConnection.GetSchema() which throws the same exception).
I don't need all of the information normally returned by GetSchema(), just the names of the PK's. Is there a good way to find out the Primary Key for a table in a SQL Server Compact database?
NOTE: The above method references are not static function calls. Consider the class name to be an object reference of that type.
SELECT INDEX_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.INDEXES
WHERE PRIMARY_KEY = 1
AND TABLE_NAME = 'MyTable';
Related
I want to do what SQL MERGE...WHEN MATCHED...WHEN NOT MATCHED does,
but with the source and destination tables on different Azure databases. (Typically on the same server if that helps.)
The source and destination tables are not exactly the same, that's why SQL MERGE would be perfect. (I can decide what column to match on, and which columns to use in the INSERT or UPDATE.)
If this can not be done in SQL, I could load the tables into my C# code and do the merge there (will affect performance though). Does anyone know if .NET has something similar to SQL MERGE in ADO.NET (merging DataTables).
Thanks for any help!
Edit: this image shows the tables before MERGE (all Values are int):
This image shows the MERGE statement and the resulting source and dest:
Azure SQL database doesn't support across database operations directly, even these databases are in the same Azure SQL Server. it will throw below error.
To work around this Azure SQL database only support the across database query with elastic query
Example
CREATE MASTER KEY; -- create master key
GO
-- credential maps to a login or contained user used to connect to remote database
CREATE DATABASE SCOPED CREDENTIAL CrossDbCred1 -- credential name
WITH IDENTITY = 'username', -- login or contained user name
SECRET = '**********'; -- login or contained user password
GO
-- data source to remote Azure SQL Database server and database
CREATE EXTERNAL DATA SOURCE source
WITH
(
TYPE=RDBMS, -- data source type
LOCATION='server.database.windows.net', -- Azure SQL Database server name
DATABASE_NAME='database1', -- database name
CREDENTIAL=CrossDbCred1 -- credential used to connect to server / database
);
GO
-- external table points to table in an external database with the identical structure
CREATE EXTERNAL TABLE [dbo].[source]
(
[Id] [varchar](50),
[value1] [int],
[value2] [int],
[value3] [int]
)
WITH (DATA_SOURCE = [source], -- data source
SCHEMA_NAME = 'dbo', -- external table schema
OBJECT_NAME = 'source' -- name of table in external database
);
GO
Now we can test our Elastic Query to merge tables.
MERGE into destination1 B
USING source E
ON (B.Id = E.Id)
WHEN MATCHED THEN
UPDATE SET value2 = E.value2, value3 = E.value3
WHEN NOT MATCHED THEN
INSERT (Id,value2,value3) VALUES (Id,value2,value3);
Output
Before merging
After merging
Using EF 6 on Net4.5
Posted a Gist showing the internal Expression and the resulting SQL created by the provider. Notice that the joins on Occasion (from BrandVisited) and BrandInfo (also from BrandVisited) are missing. Plus the provider has directly connected up BrandVisited to Respondent via RESP_ID. This is not the intended behavior and yields incorrect SQL.
Any ideas to what is happening behind the scenes?
Running local against SQL Compact but the production target database is SQL Server.
Just to make it clear. BrandVisited has foreign keys (in the EF model) to Occassion which in turn has a foreign key to Respondent. There is NO framework relationship between BrandVisited and Respondent. Despite that the provider (both SQL Compact and SQL Server) associate these table on the Respondent unique key (RESP_ID). How is this even possible?
I have an ASP.Net Web Forms app that is inserts new records (requests) into a SQL Server table using a SqlCommand and using the ExecuteNonQuery method. The table has a single primary key (int id) that is set for Identity Specification = Yes, Identity Increment 1, Identity Seed 1. The app has been working for years. About a month ago, the database was moved from a physical server to virtual server without any apparent issues. The database is running on SQL Server 10.50.1617.0.
Very recently, a user reported creating about 90 requests but not being able to find them. When I examined the request table, I could only find one request created for her in the last few days. The highest id on the request table was 5404. As an experiment, I had her create a new request. I was expecting it to create a new id of 5405, but it actually created an id of 2975. I had her create another request and it over-wrote the first request with another on id 2975. I created a test request and it created one at id 5405. What could possibly cause this?
Here is the c# for the insert:
string sql = "insert into requests (end_user_email) values (#email)";
SqlConnection cn = new SqlConnection(_cnString);
SqlCommand cmdIns = new SqlCommand(sql, cn);
cmdIns.Parameters.Add("#email", SqlDbType.NVarChar);
cmdIns.Parameters["#email"].Value = email;
cmdIns.Connection.Open();
cmdIns.ExecuteNonQuery();
Your table name is not schema-qualified (e.g., dbo.requests). I suspect you've got two different tables in your database with identical names. One is owned by the dbo schema; the other by your default schema.
SQL Server name resolution works as follows for unqualified references:
Probe the namespace for an oject of the specified name under the default schema as defined by the current connections credentials. If one is found, that object resolves the reference. Otherwise...
Probe the namespace for an object of the specified name under the dbo schema. If one is found, that object resolves the reference. Otherwise...
If the object is a stored procedure whose name begins with sp_, further probes of the namespace are performed against the master database as in steps #1 and #2 above.
Finally, if the reference was not resolved, name resolution fails.
Your user is connecting using credentials with one default schema and resolving to a table named requests that is either owned by that schema or dbo.
You, on the other hand, are using credentials with another default schema and finding a different table with the same name, either owned by your default schema or dbo.
One should always schema-qualify object references, for two-reasons:
Performance. Two probes of the namespaces to find the dbo-owned object that you probably want costs you in terms of performance.
Further, execution plans involving unqualified references may not get cached, leading to additional recompiles.
Lastly, you or somebody else will, at some point, shoot yourself in the foot. Often, it will be by one party executing one version of a stored procedure and another party a different version. Hilarity ensues -- "It works on my machine!". Even better is when different people are hitting different versions of the same table, receiving seemingly random errors regarding missing columns.
HOWEVER...
It's not unheard of :-) for identity columns to have the value of the identity property get out of sync with data for various reason.
So, if you've ruled out two different flavors of the same table, you'll want to have your DBA run DBCC CHECKIDENT against the table to get the table's identity counter back in sync with the high-water mark in the table.
DBCC CHECKIDENT( {table-name} , noreseed )
reports on the current values of both the identity counter for the table and the current high-water mark in the table.
DBCC CHECKIDENT( {table-name} , reseed )
reseeds the identity counter to match the high-water mark in the table.
It's also possible the client moved from a single server to a sand box or cloud & failed to change the web.config of the application..
<!--
If you are deploying to a cloud environment that has multiple web server instances,
you should change session state mode from "InProc" to "Custom". In addition,
change the connection string named "DefaultConnection" to connect to an instance
of SQL Server (including SQL Azure and SQL Compact) instead of to SQL Server Express.
-->
<sessionState mode="InProc" customProvider="DefaultSessionProvider">
in this case it may also benefit to move to an nvarchar(128) or GUID & use newID() to assign unique ID's to additional records.
I'm trying to retrieve records to my data gridview dgvEmployees from my table tblEmployees. I'm not sure what's wrong though, maybe because of the syntax? But the code has worked before using MS Visual C# 2010 Express (WinForms only). I'm currently creating a webpage with winforms using MS Visual Studio (ASP.NET - C#). Here's my code:
SqlConnection sConn;
SqlDataAdapter daEmp;
DataSet dsEmp;
const string sStr = "Server = MYSERVER\\SQLEXPRESS; Database = EMPLOYEES; Integrated Security = SSPI";
protected void Page_Load(object sender, EventArgs e)
{
sConn = new SqlConnection(sStr);
daEmp = new SqlDataAdapter("Select * from tblEmployees", sConn);
dsEmp = new DataSet();
daEmp.Fill(dsEmp, "tblEmployees");
dsEmp.Tables["tblEmployees"].PrimaryKey = new DataColumn[] { dsEmp.Tables["tblEmployees"].Columns["EmployeeID"] };
dgvEmployees.DataSource = dsEmp.Tables["tblEmployees"];
}
Here's the error message on this line (daEmp.Fill(dsEmp, "tblEmployees");
Invalid object name 'tblEmployees'
Please help. Thanks!
The error is referring to the SQL query not the DataSet. In other words the issue is not with the C#. You need to check your connection string and make sure the table exists in the DB.
daEmp = new SqlDataAdapter("Select * from tblEmployees", sConn);
This query is bad: Select * from tblEmployees
You can verify this by changing the query to: Select * from IDONTEXIST
You will see a similar error:
invalid object name IDONTEXIST
You are now running the application on the website so the user that will connect to SQL server is the one that is running your application pool in IIS when you use Integrated Security = SSPI in your connection string.
You need to either:
Give access to the database for the application pool user (not a good idea for the default one).
Change the user for the connection pool to a user who has access to the database.
Specify a user who has access in the connection string.
You should first verify your connection string:
Ensure it is connecting to the SQL Server instance you think it is.
Ensure that it is establishing the database context for the connection in the database you think that it is.
Ensure that it is connecting with the credentials you think that it is.
Ensure that those credentials map to the SQL Server user you think that it should
That that SQL Server user has the default schema you think it does and that it has appropriate rights granted in the database.
Almost certainly, your problem derives from one or more of the issues listed above.
If your database context for the connection is in a different database than you think, you probably won't find the objects you're looking for.
If your object references are not schema-qualified, you may have a problem resolving object references. Object references in your SQL queries should always, at the very least, be schema-qualified. Instead of saying
select * from tblEmployees
you should be saying
select * from dbo.tblEmployees
where dbo is the schema that owns the object. Any object references that are not schema-qualified are looked up at run time in the following order
First, the current user's default schema is probed for an object of the desired name.
If that fails, the dbo schema ('data base owner') is probed for an object of the desired name.
For stored procedures, the lookup is more complex:
Probe the current user's default schema in the current database.
Probe the 'dbo' schema in the current database.
If the stored procedure name begins with 'sp_',
Probe the current user's default schema in the 'master' database.
Probe the 'dbo' schema in the 'master' database.
If the object in question belongs to another schema, it will not be found unless qualified by the owner schema.
Due to the multiple lookup issue, lack of schema-qualification can prevent execution plan caching, meaning that the query plan has to be recompiled on every execution of a query. Needless to say, this has...sub-optimal effects on performance.
Further, you may get...interesting...results if your database user is 'dev' and the dev in question, 6 months back, created a table or other object named 'dev.foo' during development. Now you're live in production and connecting as user 'dev'. Executing select * from foo will bind to dev.foo in preference to the actual production table that the DBA created, 'dbo.foo'. Your users will be wondering why their data is missing or you'll be ripping your hair out wondering why the app is whining about missing columns when they appear to be all there when you look at it via the SQL Management Studio.
SQL Server 2008 R2 supports CLR integration where a .NET module can be registered in the database and can be invoked through SQL stored procedures, functions, triggers. We are able to develop such .NET modules and integrate with SQL Server.
But we have a different requirement where it is required to intercept the SELECT queries send to SQL Server (from any SQL client) and invoke a .NET module and pass the query parameters (WHERE clause) to it.
For example if we have a table (VarInfo) in database having two columns VarID (string) and Value (float). Now suppose the table contains records for 100 variables with VarID: V001 to V100. But the Value column is empty for all records. The Value data is not stored in the database. If we have a SQL select query:
SELECT Value from VarInfo where VarID = 'V001'
then the SQL Server should invoke the .NET module and pass the VarID. The .NET module shall fetch the variable Value from some external source. It shall then return the Value back to SQL Server. The SQL Server should return that Value as query output/result.
Please let know about the feasibility of the above in SQL Server 2008 R2.
Thanks,
The closest you could get would be a CLR User-Defined Function - but the calling code needs to be aware that it's a UDF and pass the parameters slightly differently, like:
SELECT Value FROM dbo.CLRUDF('V001')