Entity Framework 5 : Get Auto_Increment value before insert - c#

I currently have a table as defined as follows:
CREATE TABLE (
ID int identity(1,1) primary key not null,
field_one nvarchar(max) not null
)
I am using Entity framework 5 to insert records into this table. This aspect works and I am inserting records correctly.
field_one is a value based on the current id. For example if I have records where the max ID is 5, the next record would be inserted as (6,ABC6), and then (7, ABC7) and so on.
What I am running into is when the table is empty. The identity is at 7, and so the next record should be (8,ABC8). I Need to get the id of the auto_increment prior to the insert in order for me to apply the calculations I need when the table is empty.
How would I be able to do this since I know that the id is generated after the insert and the property is in my entity gets updated after.

You cannot get the correct identity before you perform SaveChanges. This is due to the fact that it is set by Entity Framework on insert.
However, there is a workaround to your problem.
Consider this:
// wrap in a transaction so that the entire operation
// either succeeds or fails as a whole
using(var scope = new TransactionScope())
using(var context = new DbContext()) {
var item = new Item();
context.Items.Add(item);
context.SaveChanges();
// item.ID now contains the identifier
item.field_one = string.Format("abc{0}", item.ID);
// perform another save.
context.SaveChanges();
// commit transaction
scope.Complete();
}
Yes, there are two calls to the database but there's no other way unless you are ready to go deeper than Entity Framework.

Related

Entity Framework - Updating entity's few columns only

I need some more understanding of how Entity Framework works. I have implemented code which is running ok and doing the job.
But I need to know that it is the good way or not.
I have a table with 8 columns, say
Table1
Column1 (pk)
Column2, Column3, Column4, Column5, Column6, Column7, Column8
Now when I click a button, I need to insert (if new) or update (for existing record) first 6 columns.
And on the same button click event, as part of the same process, I will call a stored procedure (with a parameter of primary key id, Column1) that will fetch these 6 columns values in the stored procedure itself and will do some calculations based on six column values and return two new values which I need to update in Column7, Column8.
So, process will be:
New record: insert (six columns data), calculations (call stored procedure), update (last 2 column)
Existing record: update (six columns data), calculations (call stored procedure), update(last 2 column)
Now, for insert, I use
_dbContext.Table1.Add(entity);
_dbContext.SaveChanges();
For existing record update (of first 6 columns), I use
//code - Entity property values are updated with new ones
_dbContext.Table1.Attach(entity);
_dbContext.Entry(entity).State = EntityState.Modified;
_dbContext.SaveChanges();
For last update, Column7, Column8, I use
var entity = GetById(Id);
if (entity != null)
{
entity.Column7 = value1;
_dbContext.Entry(entity).Property(t => t.Column7).IsModified = true;
entity.Column8 = value2;
_dbContext.Entry(entity).Property(t => t.Column8).IsModified = true;
_dbContext.SaveChanges();
}
I am not sure why I need not to attach entity for last update. Is it due to I have called GetById method for same table just above that?
Without attaching entity how it updates columns? (if I attach entity it gives error saying already being tracked)
Also, I have to call GetById multiple times to get record for both updates (in existing record scenario). Any other solution for that?
for that you can use MapToModel method
here is example
//code - Entity property values are updated with new ones
var newEntity= new Entity
{
Id = p.Id, // the Id you want to update
Column1= "" // put value for column/s that you need to update
};
newEntity.MapToModel(oldEntity);
_dbContext.SaveChanges();
IMHO I don't think you need to specify IsModified for each property if you fetch through the Context.
EF Context will automatically track Entities unless you change the default behavior
EF knows which entities are changed after loading from the database,hence it will be only updated.
Assuming GetById is fetching the data from data-store.
var entity = GetById(Id);
if (entity != null)
{
entity.Column7 = value1;
entity.Column8 = value2;
_dbContext.SaveChanges();
}
Detect Changes
Similar Question

Insert a specific id into auto incremented field in MySQL with Entity Framework 5

So this i my situation.
I have an old database with a lot, and I mean a LOT of data. However I've ended up creating a new database structure and now I want to move data from the old database into the new one. Being a programmer I'm not keen on doing it manually which is why I made a program to do just that.
Now here is my problem: When adding a new item into the new database I'm unable to set it's id, which is crucial for the different link references and general foreign key references that exists in the old database.
My question is therefore: How would I be able to insert an specified id integer into a field that has auto_increment in my MySQL database via Entity Framework 5 which uses database first in C#?
This is my MySQL script for the new database:
CREATE TABLE Profile
(
_id INT AUTO_INCREMENT PRIMARY KEY NOT NULL,
UNIQUE KEY(_id),
etc etc
)
My insert code:
public Profile Add(Profile item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
db.Entry(item).State = EntityState.Added;
db.SaveChanges();
return item;
}
On an end note I whould like to inform that I know this is bad practise in general, but the database is empty and the id inserted are auto generated and unique from the old database which will ensure that no dublicates will occour
You have to turn off identity insert, insert the records then turn on identity insert back
The solution I found where to alter the table before inserting into it. It's basicly the solution other people gave, however I needed to make a few turns.
This is what I did:
SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE Profile DROP PRIMARY KEY,
MODIFY _id INT PRIMARY KEY NOT NULL;
insert commmand here....
ALTER TABLE Profile DROP PRIMARY KEY,
MODIFY _id INT AUTO_INCREMENT PRIMARY KEY NOT NULL;
SET FOREIGN_KEY_CHECKS=1;
I came into the same problem except using Entity Framework 6, this is how I solved it:
Go into your Entity Model
Select each auto_increment field and in properties set StoreGeneratedPattern to None

get identity when adding via entity framework

I'm using entity framework to insert a new record into my templates database. I would like to know what the identity of the inserted record is after the insert is done.
my code for inserting the record...
WEBSITE_ORDER_LINE_TEMPLATES newTemplate = new WEBSITE_ORDER_LINE_TEMPLATES();
newTemplate.customerNo = Customer.CustomerNo;
newTemplate.templateName = txtSaveTemplate.Text.Trim();
dpot.WEBSITE_ORDER_LINE_TEMPLATES.Add(newTemplate);
i want to know what the templateId is... in sql, this field is set as primary key and IsIdentity=Yes.
is there a quick way to get this value without searching the database where customer and templatename match? I need to know the ID because after this part, i want to enter template line information and there's a foreign key on that table on the templateId in this table.
Call the SaveChanges() method. EF updates the newTemplate.templateId with SELECT SCOPE_IDENTITY() after the INSERT.

linq insert: getting the row number

I have a table with the primary key as the identity column. I'm doing an insert with linq-to-sql and I was wondering if there's a way to return the ID of the row that was inserted and how we know for sure that the insert happened.
Thanks for your suggestions.
The primary key property of the entity that was used for the insert will be updated after the call to SubmitChanges with the ID from the database.
Ex:
using (var dc = new MyDataContext())
{
MyEntity entity = new MyEntity();
dc.MyEntities.InsertOnSubmit(entity);
dc.SubmitChanges();
int pkValue = entity.PKColumn
}
With LINQ-to-SQL it will update any IDENTITY (etc) properties during the save automatically, so just look at .Id (or whatever).
Re knowing it happened: updates etc happen in a transaction; that transaction must have committed to have got out of the method without an exception. If you have an outer TransactionScope (or similar) then that it up to you to commit; in short - until you do commit you have a phantom record. As such, avoid passing that new id anywhere until you have committed all your transactions.
The identity of the inserted record should automatically populate the object which was added to the DataContext for the insert. Just check the ID on that object.
Additionally, you can look at the GetChangeSet() method on the DataContext to see what changes it has tracked if you want more manual information about the number of affected records, etc..

Writing to the database from LINQ in C#

I am trying to write some content to my database via LINQ. Currently, I'm getting the following error:
Cannot insert explicit value for identity column in table 'MyTable' when IDENTITY_INSERT is set to OFF.
I understand this is a primary key related issue. My table has the identity specification set to "Yes" with Identity Increment set to "1". But I have successfully updated other tables using code that looks like the following:
using (DataModelDataContext context = new DataModelDataContext())
{
List<MyTable> newRecords = new List<MyTable>();
MyTable record1 = new MyTable();
record1.CreatedBy = GetUserName();
record1.Information = GetInformation();
newRecords.Add(record1);
MyTable record2 = new MyTable();
record2.CreatedBy = GetUserName();
record2.Information = GetInformation();
newRecords.Add(record2);
context.MyTables.InsertAllOnSubmit(newRecords);
context.SubmitChanges();
}
What would cause this error? If I want to write new records, is there a way to set the primary key before it gets sent to the db? Something like "GetNextKey()" or something? Basically, I just need to insert these records. What am I doing wrong?
Thanks!
The code you have posted would work, assuming neither of those fields have the identity value. You basically need to assure you do not try to set the identity value before you add the item to the Table collection. (actually, you should never set the identity value from your code in most circumstances when it is to be generated in the DB).
So somewhere, the code that is having an error is trying to set the identity field's value.
If the ID is important (say you're importing data, and records you'll be inserting later will reference these records), then turn off the identity temporarily while you perform the insert. If having a particular ID on each record doesn't matter, and you can let the identity column pick one (which is 99.9 percent of the time), make sure you're not specifying a value for the ID before trying to save the record. Also make sure that your mapping between the object and the DB specifies that the ID is an identity, so EF knows not to try to insert the ID column.
Check to make sure your primary key/identity column has the following set within the DBML:
Auto Generated Value: True
Auto-Sync: OnInsert
This will make sure that LINQ-To-SQL will not try and insert the key value into that column and that it will update the value after an insert takes place. These should be on when you added the table to the DBML.

Categories