Duplicate Records in SQL Server with Identity Column - c#

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.

Related

Cannot insert the value NULL into column, table; Column does not allow nulls... But this column is Primary Key and has autoincrement property

I have published a web app, it's running on azure. The web app project I was testing on my computer (localhost) and then on the web app. When I tested to create a new row a data (for example a new person on a PersonTable) It worked on my localhost but when I tested the web app published it throws this error:
Cannot insert the value NULL into column 'ID_ANTEC_PERS', table
'Telejdb.dbo.ANTECEDENTES_PERSONALES'; column does not allow nulls.
INSERT fails. The statement has been terminated.
That column (ID_ANTEC_PERS) is the ID of that table(ANTECEDENTES_PERSONALES), but I set to this column the identity(1,1) property on my sql server DB. When I worked this project in my computer (localhost) I hadn't this problems, I think it is because the project knew the sequence of that auto increment property. But now, once the web app is published and running on azure, I wanted to see the code of my project but I realized it was compiled on .dll files So I can't edit the web app project. Any Help? Guide? Suggestions? I will appreciate that.
Thanks in advance
Check the field from your table design then Check the checkbox from your table design then it allows to insert null value in table
id is supposed to be an incrementing value.
You need to set this, or else if you have a non-nullable column, with no default value, if you provide no value it will error.
To set up auto-increment in SQL Server Management Studio:
Open your table in Design
Select your column and go to Column Properties
Under Indentity Specification, set (Is Identity)=Yes and Indentity Increment=1
in local if you are not getting this problem means you have to update the
azure database
Finally I could solve it, the problem was my azure DB tables didn't have identity property (autoincrement) so the table had a PK but it doesn't have their identity property.
What happen?
When I tried to import my local DB (which all its tables have the identity property) to azure DB I didn't by a unknown method (I used the task of SSMS: Task>Export Data...) This could import all the tables, PK Constraints and all the data but it didn't import all the identity properties.
How to fix it?
What I did to solve it was importing my database again but this time in a correct way: importing my local db to azure db by a bacpac file (azure database recognizes this kind of backup file).
Actually, before I used the method to import my DB that I used, I tried importing my db by importing bacpac file but I couldn't because I used SSMS 2014 and researching on another stackoverflow questions I figured out I can't make a bacpac file with SSMS 2014 (I had a problem with clustered Index) but I can do it with SSMS 2016, so I installed it and finally I could create the bacpac file and then I could import it to my azure db, and it had the identity property

Using WCF Data Services to copy one database table to another

I am little stuck in using LINQ to insert one database table to another database table located on another server as a WCF Data Service.
Suppose I have an Item class on the local database and the same Item class on the the remote server, and I want to copy all the records across.
Is there a possibility to do this from: -
private Uri svcUri = new Uri("someurl/WcfDataService.svc");
Entities = new Entities(svcUri);
.....
I know that LINQ to SQL is mostly a 1-1 mapping between classes and the database, but I heard it is possible.
You just need to construct a connectionstring pointing at the right database. That database has to have the tables the EF expects to have though. (The code would look like yours, but I've never used a Uri for a connection string.)
However, it would be more efficient to do via a stored procedure on your source database, via a Linked Database to y=the Target. This because if you do it via WCF the data has to travel twice: SourceDB -> WCF service -> TargetDB, whereas with a SP it only has one hop: SourceDB -> TargetDB. Also in the SP it will operate pretty much as a set operation whereas the WCF service will have to process one row at a time.
EDIT - Apologies: I didn't notibe the MySQL tag. I don't know whether MySQL supports Linked Databases, so feel free to ignore this if it doesn't.

C# Invalid object name ASP.NET

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.

Inserting different data simultaneously from different clients

I created a windows forms application in C #, and a database MS SQL server 2008 Express, and I use LINQ-to-SQL query to insert and edit data.
The database is housed on a server with Windows Server 2008 R2 (standard edition). Right now I have the application running on five different computers, and users are authenticated through active directory.
One complaint reported to me was that sometimes when different data is entered and submitted, the same data do not appear in the listing that contains the application. I use try catch block to send the errors but errors do not appear in the application; but the data simply disappear.
The id of the table records is an integer auto-increment. As I have to tell them the registration number that was entered I use the following piece of code:
try{
ConectionDataContext db = new ConectionDataContext();
Table_Registers tr = new Table_Registers();
tr.Name=textbox1.text;
tr.sector=textbox2.text;
db.Table_Registers.InsertOnSubmit(tr);
db.SubmitChanges();
int numberRegister=tr.NumberRegister;
MessageBox.Show(tr.ToString());
}
catch{Exception e}
I wonder if I'm doing something wrong or if you know of any article on the web that speaks how to insert data from different clients in MSSQL Server databases, please let me know.
Thanks.
That's what a database server DOES: "insert data simultaneously from different clients".
One thing you can do is to consider "transactions":
http://www.sqlteam.com/article/introduction-to-transactions
Another thing you can (and should!) do is to insure as much work as possible is done on the server, by using "stored procedures":
http://www.sql-server-performance.com/2003/stored-procedures-basics/
You should also check the SQL Server error logs, especially for potential deadlocks. You can see these in your SSMS GUI, or in the "logs" directory under your SQL Server installation.
But the FIRST thing you need to do is to determine exactly what's going on. Since you've only got MSSQL Express (which is not a good choice for production use!), perhaps the easiest approach is to create a "log" table: insert an entry in your "log" every time you insert a row in the real table, and see if stuff is "missing" (i.e. you have more entires in the log table than the data table).

SQL Database Mirroring and your web application

You have two servers when you perform a SQL Server database mirroring
You have 1 primary database and 1 mirror database
Do you need to make any changes to web application to tell it that your using database mirroring? If not how does your web application know which database to use when the primary database fails?
It can be set in the connection string. See the "database mirroring" example here
Do you need to make any changes to web application to tell it that your using database mirroring?
Yes, add the Failover Partner parameter to your connection string, using either the IP or instance name. IE: (line returns for readability)
Data Source = myServerAddress;
Failover Partner = myMirrorServerAddress;
Initial Catalog = myDataBase;
Integrated Security = True;
The mirror doesn't have to exist to test the failover - you can use a dummy address as the Data Source and watched our application use the valid config in the Failover Partner.
But mirroring does not cover logins or jobs - this link provides a script for cloning logins from SQL Server 2005 to other 2005+ instances. You will have to use either ALTER USER or sp_change_users_login to sync the logins if the SIDs are not identical on the principal and mirror.

Categories

Resources