Inserting Entity into SQL Compact 4 Table with Identity column using LINQPad - c#

I'm trying to insert new records into a SQL CE 4 database with LINQPad and having problems with the identity problem of a table. Let's say I have this simple table for instance:
PEOPLE
Id int IDENTITY(1,1) NOT NULL,
Name nvarchar(100) NOT NULL
I may be doing things the wrong way but I tried this in LINQPad
People person = new Person { Name = "Bob" };
People.InsertOnSubmit(person);
SubmitChanges();
But I get a SqlCeException stating
"The colum cannot be modified. [ Column name = Id ]"
I can insert a record with SQL just fine, that works with no errors from SQL CE or its data provider and SQL CE sets the Id column for me which is what I'm wanting
INSERT INTO PEOPLE (Name) VALUES ('Bob');
Is there another step that I'm missing? I'm not even sure if its a LINQPad issue but thought I'd ask anyways since that's what I'm trying this code with right now.

What do you get if you run this in LinqPad
(from dm in this.Mapping.GetTable(typeof(People)).RowType.DataMembers
select new { dm.DbType, dm.Name, dm.IsPrimaryKey , dm.IsDbGenerated }
).Dump();
In particular, as I understand it, IsDbGenerated should be true for the id column.
I have a SQL CE 3.5 data file that I have used previously in LinqPad and looking at the SQL generated for inserts it does not mention id

This is probably the issue with dbml file. Check whether the column is marked as identity(or whatever this is called in L2S). The thing is that Id cannot appear in the insert query.

Related

Adding SQL Server ID Increment upon registration

How would I retrieve an Id from my SQL Server table, add +1 to it, and register that number to the next Id when someone registers into my program?
This is my code so far. The ?? means I don't know what would go there for this to work.
SqlCommand hi = new SqlCommand("SELECT MAX(Id) FROM Table");
hi.CommandType = CommandType.Text;
hi.Connection = connection;
hi.Parameters.AddWithValue("#Id", ??);
For example, last Id was 14. Now someone is registering and I want it to say 15 in the SQL Server table under Id.
I'm not sure what your full table structure is like, but the functionality you're describing is available natively in a SQL Server databases, and it's called an identity column. The way you would implement it is like this:
CREATE TABLE MyTable
(
Id int not null identity(1,1),
Name nvarchar(255) not null
# other columns go here...
)
You should be able to alter an existing table to make an Id column use identity, the only catch is you can only have one identity column per table.
When you want to insert a new record into the table, you can leave the identity column out of your insert statement, as SQL Server will fill it with the appropriate value:
INSERT INTO MyTable (Name)
VALUES ('My Name')
I would suggest to handle it at database level by making ID column auto increment.
If you want to do it from your code then you have to make additional hit to database to get last ID before you make your insert call to add data.

Query on Identity Column on MS SQL DB

I have created table in MS SQL 2008 with one identity column(Start Value - 1 and Increment is also 1) and 4 other columns. I am accessing this DB from C# ASP.NET. Used to push data only for the non identity column. Identity column will auto increment itself.
As of now i am manually querying the column value with the remaining for columns. But I am facing problem if all the other four column values are equal i am not getting the exact value which i am looking for
Now my query is, Is there any why in C# where I can get the value of the newly created identity column whenever new record is created.
Thanks.
You can use
SCOPE_IDENTITY()
Which will returns the primary key value of the recently inserted row
The answer to your question actually lies in SQL Server. You can run:
SELECT ##identity
after your insert to get the last inserted row identity.
http://technet.microsoft.com/en-us/library/aa933167(v=sql.80).aspx
EDIT BASED ON COMMENTS:
Consider using SCOPE_IDENTITY() as referenced here:
http://technet.microsoft.com/en-us/library/aa259185(v=sql.80).aspx
In SQL terms you can output the records back if you wish it. But how you might apply this to C# is up to you. Example:
INSERT INTO TABLE_A (SOMETHING, SOMETHINGELSE, RANDOMVAL3)
OUTPUT inserted.A_ID, inserted.SOMETHING, inserted.SOMETHINGELSE, inserted.RANDOMVAL3
SELECT 'ASD','DOSD', 123
But unless you're using merge, you can't use OUTPUT to print out any values from joining tables from an INSERT. But that's another matter entirely, I think.
Also, it's hardly good practice to bounce this data between the application and the DB all the time, so I'd look to alternatives if possible.

ORA-01400 when trying to insert into schema.table.ID

I have a table that stores rejected contract proposals.
CREATE TABLE "STATUS_CONTRATO" (
"STC_ID" NUMBER NOT NULL,
"CTB_CONTRATO" NUMBER NOT NULL,
"STC_DATA" DATE NOT NULL,
"STC_OBSERVACAO" VARCHAR2(200) NOT NULL,
CONSTRAINT "STATUS_CONTRATO_PK"
PRIMARY KEY ( "STC_ID")
ENABLE
VALIDATE,
CONSTRAINT "FK_CONTRATO"
FOREIGN KEY ( "CTB_CONTRATO")
REFERENCES "CONTRATO" ( CTB_CONTRATO)
ON DELETE SET NULL
ENABLE
VALIDATE)
;
(Script generated by Visual Studio 2010)
This table has a simple Trigger, where the value of STC_ID is set:
TRIGGER "STATUS_CONTRATO_TRIGGER1"
BEFORE
INSERT
ON "STATUS_CONTRATO"
FOR EACH ROW
when (new.STC_ID = 0)
DECLARE
BEGIN
SELECT SEQ_STATUS_ID.NEXTVAL INTO :NEW.STC_ID FROM DUAL;
END;
SEQ_STATUS_ID is a simple sequence.
Here's my problem:
I can successfuly execute this insert in the VS2010 query window:
insert into myschema.STATUS_CONTRATO s(
s.STC_ID, s.CTB_CONTRATO, s.STC_DATA, s.STC_OBSERVACAO
)values(
0, 10, SYSDATE, 'Inserting by hand works'
);
But, when I try to insert using EF, I'm getting this exception:
System.Data.UpdateException: An error occurred while updating the entries.
See the inner exception for details. ---> Oracle.DataAccess.Client.OracleException:
ORA-01400: cannot insert NULL into ("MYSCHEMA"."STATUS_CONTRATO"."STC_ID")
ORA-06512: at line 4
I'm using this code to insert
STATUS_CONTRATO statusContrato = new STATUS_CONTRATO() {
STC_ID = 0,
CTB_CONTRATO = codContrato,
STC_DATA = DateTime.Today,
STC_OBSERVACAO = observacao
};
ent.STATUS_CONTRATO.AddObject(statusContrato);
ent.SaveChanges();
I'm using VS2010, Oracle 11g (CentOS Server), ODP.NET client 11.2.0.3.0 Production, .NET Framework 4.0, EF 4.
Check this: http://www.oracle.com/technetwork/issue-archive/2011/11-sep/o51odt-453447.html
Particularly, section "Triggers and Sequences"
From the Tools menu, select Run SQL Plus Script. Browse to the
location where you extracted the code and scripts, select the
triggers.sql script, select the HR connection from the list, and click
Run. The INSERTEMPLOYEES trigger created by the script generates a new
sequence for EMPLOYEE_ID whenever NULL is passed in for that value........
Your code works, except for a problem with
ent.UNV_STATUS_CONTRATO.AddObject(statusContrato);
Is UNV_STATUS_CONTRATO another table? Why is it not
ent.STATUS_CONTRATO.AddObject(statusContrato);
That should work just fine.
However, you might find it preferable to get the sequence value from your code and apply it to your ID column in memory before saving changes. So something like this:
public static int GetSequenceNextVal()
{
using (YourEntities entities = new YourEntities ())
{
var sql = "select myschema.SEQ_STATUS_ID.NEXTVAL from dual";
var qry = entities.ExecuteStoreQuery<decimal>(sql);
return (int)qry.First();
}
}
Then you call that method before SaveChanges().
Personally, I prefer to handle it this way so that my in-memory entity then also has the correct ID, instead of just having a 0, or having to query it right back out, etc.
Also, the method described here under Triggers and Sequences can supposedly wire up an entity's PK to a sequence.
You need to specify in your EF Mapping that the DB does not generate the key for you and EF should use the Key you provided...
see my post in the following thread:
https://stackoverflow.com/a/18635325/1712367

How to obtain the identity of an entity after calling SaveChanges() when the entity is mapped to stored procedures

We are using Entity Framework 4.0 and we have an entity that is mapped to stored procedures provided by our DBA. The Insert, Update, and Delete functions in the mapping details all have their own stored procedures.
When using entities that are mapped to tables I am able to add a new entity, call dataContext.SaveChanges(); and then the new entity I instantiated automatically has its ID property populated with the value from the identity column in the database.
How can this be accomplished when the entity is mapped to stored procedures? Does the INSERT stored procedure have to do something special and/or do I have to do something special on dataContext.SaveChanges();?
Example
Traditional way
var newCustomer = new Customer
{
Name = "Fred",
Age = 24
};
// newCustomer.Id is null
dataContext.Customers.Add(newCustomer);
dataContext.SaveChanges()
// newCustomer.Id is what database identity column was set to.
Mapped to stored procedures.
var newCustomer = new Customer
{
Name = "Fred",
Age = 24
};
// newCustomer.Id is null
dataContext.Customers.Add(newCustomer);
dataContext.SaveChanges()
// newCustomer.Id is null
If you are using Identity column in database make sure that your stored procedure contains:
SELECT Scope_Identity() AS Id
after calling INSERT
Also make sure that PK in your entity mode is correctly configured with StoreGeneratedPattern set to Identity (should be automatically if you used Update from database)
I believe your DB needs to use ##identity or insert with a NewID() and return the Identity/NewID value back to you via the stored procedure. You technically could select from the database for the record you inserted, but that is a very questionable way to do it as; you don't know if the records was inserted (unless the SP failed at .Net), you may not know if duplicated records exists, or even if the data was changed after the insert but before the select. When in doubt I always highly recommend talking to your DBA about the best approach to your specific needs based your DBAs design.
Updates:
If he returns you the PK value, you should be able to do a standard select from the table to populate the entity like from e in context.entities where e.pkcolumn = spkeyreturned select e.
If he returns you ALL the data back, and can guarantee the data won't change, you might be able to create a new entity, populate it will all the data and use the Attach method. I personally wouldn't do that, but it is an option. Attaching and Detaching Object in Entity Framework.

Violation of PRIMARY KEY constraint Cannot insert duplicate key in object . In C#.net....Visual Studio 2010...framework 3.5

I'm Developing a small windows application in C#.net in Visual Studio 2010 with framework 3.5. I use LinqToSql for database manipulation.
table name: cprofile
Fields of the table are:
custid int (primary key),
custname varchar(50),
address nvarchar(MAX),
mobileno nchar(10)
So i have changed the 'Is identity' property of the 'cust id' to 'yes'. It automatically changes other 2 sub properties.
Identity Increment = 1
Identity Seed = 1,
After these changes have been made in the table, it throws error when I try to save a new record.
"Cannot insert explicit value for identity column in table 'cprofile'
when IDENTITY_INSERT is set to OFF."
Not too familiar with L2S, but I'd say Daniel is correct: update your model (usually on a context menu somewhere) from the DB. That should prevent it from attempting to insert a value into your auto-incrementing ID column.
I believe there may be a way to have it set IDENTIY_INSERT ON, but I highly recommend against it.
If your table should not be in charge of setting the CustomerId (say, the business has some method of making that determination (especially in a non-linear way), leave your Customer Id column as the PK, but remove the Identity specificaiton from the column.
If you're trying to use the same insert statement you were using before, you can no longer do that. I'm not sure how it's done in the C# side of it, but in SQL, you'd have to run statements to turn identity_insert on, then run your statement. Because you changed the column to identity, the table makes sure the next entry is always 1 number higher than the previous. Because of this, you can't simply insert values into it. If you want the table to create the identity value for you, simply remove it. If my explanation doesn't help, hopefully this will.
Table Definition (Table1)
Col1 Identity
Col2 varchar(50)
Col3 bool
Insert statement before identity
INSERT INTO Table1 VALUES (1, 'Test', TRUE)
Insert statement after identity
INSERT INTO Table1 VALUES ('Test', TRUE)
When identity is on, you cannot specify the value without turning on identity_edit. I'll see if I can find how to do that in Linq.
EDIT: I also like what Daniel said. Didn't think about that.

Categories

Resources