Why isn't the new row being added to my database table? - c#

Here's my code:
private void button1_Click(object sender, EventArgs e)
{
var dbContext = new DataClasses1DataContext();
var record = new AutorizedActivity();
record.MbrId = (int) ddlMember.SelectedValue;
record.ActId = (int) ddlActivity.SelectedValue;
dbContext.AutorizedActivities.InsertOnSubmit(record);
dbContext.SubmitChanges();
}
Basically, the form has two dropdownlists. The user makes a selection from each list and presses the button to update a table with their selections.
The problem is, no data is ever being added to the table. No errors occur at all. I've stepped through in debug, and can't see anything wrong. Are there any common things I could check to determine why the program appears to insert a record, but nothing is actually inserted?
Here's my table definition:
CREATE TABLE [dbo].[AutorizedActivities] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[MbrId] INT NOT NULL,
[ActId] INT NOT NULL,
CONSTRAINT [PK_AutorizedActivities] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_AutorizedActivities_AvailableActivities] FOREIGN KEY ([ActId]) REFERENCES [dbo].[AvailableActivities] ([Id]),
CONSTRAINT [FK_AutorizedActivities_Members] FOREIGN KEY ([MbrId]) REFERENCES [dbo].[Members] ([Id]));
Here's the datacontext layout, for clarity:
SOLUTION: The database table was being updated... just not the one I was looking at. I was running the program in debug mode, which places a copy of the .mdf in the debug/bin directory. I wasn't looking at that table; I was looking at the table in my production directory. If I had ran the program in release mode, it would have worked like a charm and updated the live table, as opposed to the test (debug) version.

Two things might help here, but it's impossible to give a definite answer on this one - you're gonna have to try things. The first things I would try here are changing to the 'standard' structure for EF code, which will "Close/Dispose" the context, and making sure your identity property is set correctly on the Entity itself. Sometimes VS doesn't do that automatically. So, check that setting and change the code to this...
using (var dbContext = new DataClasses1DataContext()) {
var record = new AutorizedActivity();
record.MbrId = (int) ddlMember.SelectedValue;
record.ActId = (int) ddlActivity.SelectedValue;
dbContext.AutorizedActivities.Add(record);
dbContext.SubmitChanges();
}
Also... did you misspell "Authorized" - fix that now before it's too late and you propogate that through the whole app.

The database table was being updated... just not the one I was looking at. I was running the program in debug mode, which places a copy of the .mdf in the debug/bin directory. I wasn't looking at that table; I was looking at the table in my production directory. If I had ran the program in release mode, it would have worked like a charm and updated the live table, as opposed to the test (debug) version.

Related

Add a non existing Primary Key in a SQL server table

I want to insert data in a table that has integers as primary keys. The primary keys will be added by a wide range of random numbers. First I want to check if the primary key exists and then insert it.
Here is my code:
public static void Insert()
{
bool a=true;
while (a != false)
{
try
{
db.test.Add(new test() //insert into test table new data
{
Id = rand.Next(1, 10),
name = "test",
surname = "test"
});
db.SaveChanges();
a=false;
}
catch (Exception)
{
Console.WriteLine("Duplicate");
}
}
}
In the first iteration if the number is not duplicate I can successfully insert the new row in database. If in the first iteration it is duplicate entry after db.SaveChanges();i jump directly in catch. But the problem arises when in the second iteration the random number is not duplicate it still jumps to catch exception without executing the a=false line of code.
Any Idea?
Note: I am not interested on using GUIDs or any other data type.
I might have an easier solution for you if you don't NEED it to be a random number.
CREATE TABLE Persons (
ID int IDENTITY(1,1) PRIMARY KEY,
Surname varchar(255) NOT NULL,
Name varchar(255)
);
INSERT INTO Persons (Name,Surname)
VALUES ('Lars','Monsen');
This way you don't even need to do anything with the PRIMARY KEY, SQL Server will handle it for you!
The issue here is that once a duplicate key has been generated, it will fail to insert, so it will keep trying to insert it each time; to quote OP:
Yes exactly, when it detects a duplicate it keeps trying it even though the next number may not be a duplicate.
There are 3 main ways of solving this:
don't generate your own keys; sorry, but this is the simplest, most obvious, and most supportable mechanism here; IDENTITY is your friend
if you fail to insert something : remove that same something from your ORM context so you don't keep failing; there is presumably a db.test.Remove method that will suffice; you may also be able to just change the value in the last row, abusing the fact that you know it was the last row that failed: db.test.Last().Id = newId; - this is very odd though; everything gets weird if you change identity keys
or alternatively, don't keep re-using the data context after failure; assuming that db is now unusable after the exception, and create a new one for any subsequent operations; IMO this should be done by the same code that originally created the db-context, in a "redo from start" way

Alter column identity with Microsoft.SqlServer.Smo

I've trying to change a column IDENTITY using Microsoft.SqlServer.Smo from a table with no dependencies and with all the data loaded previously (from another DB) but i get an error like this "Modifying the Identity property of the Column object is not allowed. You must drop and recreate the object with the desired property". The thing is that i tried to do this with Management Studio and it has no problem with it. Do you have any suggestions?. Thanks in Advance
This is the code:
foreach (Column source in sourcetable.Columns)
{
try
{
if(source.Identity)
{
Column column = copiedtable.Columns[source.Name];
// column.Computed = source.Computed;
// column.ComputedText = source.ComputedText;
column.Identity = source.Identity;
column.IdentityIncrement = source.IdentityIncrement;
column.IdentitySeed = source.IdentitySeed;
column.Alter();
}
}
catch { }
}
Try doing it in SSMS again and choose to script the action out instead of applying it directly. You'll find that it creates a temporary table with the identity property set to true (and everything else the same), copies your data from the live table into the temp table, drops the live table, and renames the temp table to be the live table. You'll need to do something similar with SMO.
Copying the table is easy enough: iterate over the columns, indexes, foreign keys, etc and create your new table that way (taking care to set the identity property correctly properly before you call Create()). For moving the data, take a look at the Transfer class. Once that's done, it's a drop and rename (or a rename and rename if you want to be safe).
I'm a little surprised that SMO doesn't do this somehow under the covers (since SSMS uses SMO under the covers). If I find something else that makes it do this automatically, I'll let you know.
Are you trying to update an existing record, or add a new record? If you're adding a new record, then do an insert. If you're updating an existing record, don't overwrite the identity column value.
To insert identity values into a table in SQL Server you must tell the database to allow you to do this. Syntax is:
Set Identity_Insert [table] ON
When you're done you need to turn it off again.
Set Identity_Insert [table] OFF

In C#, SQLite randomly throws "Constraint failed\r\nColumn ... is not unique"

I'm using EntityObjects in C# and my backend is SQLite. System information:
Windows XP (up-to-date), VS2010 Premium, System.Data.SQLite 1.0.88.0 (3.7.17)
The table schema is:
CREATE TABLE [transaction] (
[primary_key_col] integer PRIMARY KEY AUTOINCREMENT,
[transaction_code] int NOT NULL,
[account_code] int NOT NULL,
[category_code] int NOT NULL,
[transaction_date] date NOT NULL,
[description] varchar(50));
public partial class Transaction : EntityObject represents this table.
To add a new Transaction, I call the following code:
Transaction transaction = new Transaction()
{
description = _desc,
transaction_code = generateHash(_desc),
account_code = _acccode,
category_code = _catcode,
transaction_date = DateTime.Now
};
dbEntities.Transactions.AddObject(transaction);
dbEntities.SaveChanges(System.Data.Objects.SaveOptions.AcceptAllChangesAfterSave);
Works fine but after adding a few rows, I get the following exception:
Constraint failed\r\nColumn account_code is not unique.
If I exit the application and restart it, this error goes away but then randomly comes back again.
I know account_code is not unique, I never asked for it to be unique!!!
There are only 3 specific ways the application can create a transaction and this exception is thrown rather randomly from any of these methods. Is this something to do with SQLite? (I'm new to SQLite). Any idea why this is happening? I've nearly pulled out all my hair ...
As per comment which seems to have done the trick:
Are you using a "new" dbEntities context every time you do an insert or are you re-using the same one for multiple inserts? It shouldn't matter either way but I would try the former if you are currently using the latter.

SubSonic not recognizing SQLite foreign keys

I'm using SubSonic 3.0.0.3 and I can't seem to get the ActiveRecord .tt files to recognize and generate code for the foreign keys and relationships in my SQLite database.
I think it generates everything else just fine, but after looking at other snippets online it looks like there should be more generated code than just single classes in ActiveRecord.cs and Structs.cs for each of my tables. Looking inside Structs.cs, IsForeignKey is always false for every column, even the ones I have a foreign key defined for. Additionally, each Foreign Keys region is empty within each generated ActiveRecord class.
I'm using VS2008 with references to SubSonic 3.0.0.3, System.Data.SQLite 1.0.66.0, and System.Data.SQLite.Linq 2.0.38.0 in my project. I created the database using SQLite Expert Personal 3.1.0.2076. I made some dummy tables to try to test out how SubSonic handles one:many and many:many relationships. Here's the DDL SQLite Expert spits out for my small database:
CREATE TABLE [Person] (
[PersonID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[PersonName] TEXT NOT NULL,
[PersonAge] INT NOT NULL
);
CREATE TABLE [Group] (
[GroupID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[GroupName] TEXT NOT NULL,
[GroupDescription] TEXT NOT NULL
);
CREATE TABLE [Dog] (
[DogID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[PersonID] INT NOT NULL CONSTRAINT [DogPersonFK] REFERENCES [Person]([PersonID]) ON DELETE CASCADE ON UPDATE CASCADE,
[DogName] TEXT NOT NULL);
CREATE TABLE [GroupPersons] (
[GroupID] INTEGER NOT NULL CONSTRAINT [GroupPersonToGroupFK] REFERENCES [Group]([GroupID]) ON DELETE CASCADE ON UPDATE CASCADE,
[PersonID] INTEGER NOT NULL CONSTRAINT [GroupPersonToPersonFK] REFERENCES [Person]([PersonID]) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT [sqlite_autoindex_GroupPersons_1] PRIMARY KEY ([GroupID], [PersonID]));
I know foreign keys are enabled and work in the database - SQLite Expert says they're on and when I change data in one place, like Person's PersonID, it does indeed change that PersonID in the Dog and GroupPersons tables. I've tried re-adding the database to the project, 'running custom tool' to get the .tt files to execute again, and even deleting them and adding them back. I can get a simple project to build that perform simple querying and insertions, however I tried just now to change the primary key of a single Person, Dog, or Group and x.Save() but System.Data.SQLite threw an exception for all three, saying SQLite error near "WHERE":syntax error. at the Save().
Any suggestions for what I should try to do next?
It seems that the FKTables attribute for each table is not assigned in the file "SQLite.ttinclude". So i add some lines of code and managed to generate foreign key code :
After line 16 (var schema = conn.GetSchema("COLUMNS");), insert :
var schemaForeignKeys = conn.GetSchema("FOREIGNKEYS");
After line 29 (tbl.Name = row["TABLE_NAME"].ToString();), insert :
tbl.FKTables = new List<FKTable>();
var foreignKeyTables = schemaForeignKeys.Select("TABLE_NAME='" + tbl.Name + "'");
foreach (var foreignKeyTable in foreignKeyTables) {
FKTable foreignKey = new FKTable();
foreignKey.ThisTable = foreignKeyTable["TABLE_NAME"].ToString();
foreignKey.ThisColumn = foreignKeyTable["FKEY_FROM_COLUMN"].ToString();
foreignKey.OtherTable = foreignKeyTable["FKEY_TO_TABLE"].ToString();
foreignKey.OtherColumn = foreignKeyTable["FKEY_TO_COLUMN"].ToString();
foreignKey.OtherClass = CleanUp(foreignKey.OtherTable);
foreignKey.OtherQueryable = foreignKey.OtherClass;
tbl.FKTables.Add(foreignKey);
}
And after line 53 (col.IsNullable=row["IS_NULLABLE"].ToString()=="True";), insert :
col.IsForeignKey = tbl.FKTables.Any(x => x.ThisColumn == col.Name);
This is for generate the foreign key code.
Moreover, you have maybe encounter a problem when you have to delete a record which has a column to be a foreign key in an other table ? For exemple :
Person(Id, Name)
Dog(Id, #PersonId)
If you have set the #PersonId foreign key on-delete action to "SET TO NULL", this won't work because foreign key support is disabled by default in SQLite 3.6.23.1 (version used by Data.SQLite 1.0.66.0).
To enable foreign key support, you have to execute this command with each connection :
PRAGMA foreign_keys = ON;
Now, this is not supported by Data.SQLite, but it will (in version 1.0.67.0, http://sqlite-dotnet2.cvs.sourceforge.net/viewvc/sqlite-dotnet2/SQLite.NET/System.Data.SQLite/SQLiteConnection.cs?r1=1.80&r2=1.81).
So you have to wait for the release or you can (like me) download the Data.SQLite source and compile the last version. It work great for me.
Good luck.
And sorry for my english :)
I'm trying to reason this. There seems to be two issues at hand:
Subsonic not recognising your foreign keys
The x.Save() function sending that error message.
SQLite will be enforcing referential integrity on its own, so while Subsonic does not see the foreign references, SQLite does, and that's why your updates go through. Subsonic does not drive SQLite, it is driving itself, which is fine.
I'm attempting to learn what SubSonic is and does. In the mean time, I have this hypothesis: the table definitions are not parsed correctly. If x.Save() is uses automatically generated SQL, it could be that the two issues are really just one.
To validate (or invalidate) this hypothesis, could you try defining the tables thus, giving the foreign keys as table attributes, not attributes of specific fields:
CREATE TABLE [Dog] (
[DogID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[PersonID] INTEGER NOT NULL,
[DogName] TEXT NOT NULL,
FOREIGN KEY ([PersonID]) REFERENCES [Person]([PersonID]) ON DELETE CASCADE ON UPDATE CASCADE);
CREATE TABLE [GroupPersons] (
[GroupID] INTEGER NOT NULL,
[PersonID] INTEGER NOT NULL,
FOREIGN KEY ([GroupID]) REFERENCES [Group]([GroupID]) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY ([PersonID]) REFERENCES [Person]([PersonID]) ON DELETE CASCADE ON UPDATE CASCADE,
PRIMARY KEY ([GroupID], [PersonID]));

SubmitChanges() doesn't work

I don't know what's wrong with this code , this code compile successfully but doesn't update database . do i miss some thing ?
DataClassesDataContext db = new DataClassesDataContext();
var query = from p in db.AllPatiences
select p;
int newID = 1001;
foreach (AllPatience patient in query)
{
patient.Id = newID.ToString();
newID++;
}
db.SubmitChanges();
My guess is that you're working with a file-based database (.mdf) in your project, and you're trying to look at the table data in that database. When you build your project, the database is cloned into the bin/debug/ or bin/release/ directory, where your running program accesses it. If you take a look at this version of the file, rather than the one you have loaded into your VS project, you should see the changes.
If this is the case, you should set the database file property to "Copy only if newer" or "Do not copy", to avoid it cloning the DB each build.
is patient.Id generated in the database itself? Possibly as an SQL IDENTITY field?
Also, check the SyncOn property of the field in your dbml file.
I found the problem , For Update like that , It's necessary to have primary key . The reason my table didn't have primary key was : I imported those data from an Excel file , So i didn't have Primary key .
Guess, is "Id" your tables primary key? If so, I don't think that L2S supports an update of the primary key (what's very correct in my opinion). You should never attend to change the value of the primary key.
If Id is not your primary key, I have no clue :-P.

Categories

Resources