I'm developing an ASP.net application using Entity Framework. I'm using DetailsView to insert data into database. There is a table as Client and its primary key is client_id. client_id is auto generated by database. I need to get auto generated client_id after inserting a record into Client table and assign it to a hidden field for future use.
I searched about this and I found lot of solutions. But I don't know how to use them since I'm new to asp.net. I found that Entity Framework automatically populates business objects with the db-generated values after call SaveChanges(). My question is where should I call this in my partial class ? What is the event ?
I'm using DetailsView with EntityDataSource and binding EntityDataSource directly with Entity Model, so I'm not creating objects to insert data.
Following the call to _dbContext.SaveChanges(), the entity will automatically be updated with its new identity field value.
The following code assumes your Entity Framework entity container name is MyEntities, and your database's Client table has at least the two following fields:
client_id int identity
client_name varchar(25)
Your code might look something like this:
// Establish DbContext
private readonly MyEntities _dbContext = new MyEntities();
// Create new client table entity and initialize its properties
var clientEntity = new Client { client_name="MyCo" };
// Add it to the ORM's collection of Client entities
_dbContext.Clients.Add(clientEntity);
// Save the new entity to the database
_dbContext.SaveChanges();
// Return the identity field from the existing entity,
// which was updated when the record was saved to the database
return clientEntity.client_id;
After you have inserted the entity it should be updated so that the property that maps to the primary key in the database has the new PK value.
Like MyObject.Id will give you the new Id
This is what I'm looking for.
in partial class
protected void clientDataSource_OnInserted(object sender, EntityDataSourceChangedEventArgs e )
{
int newPrimaryKey = ((Client)e.Entity).ClientId;
Debug.WriteLine(" Client ID is " + newPrimaryKey);
}
and added below line in EntityDataSource in aspx page.
OnInserted="clientDataSource_OnInserted"
Thanks, I spent 3 days searching and searching with complicated results but this solution is brilliant! Here it is in vb.net:
Protected Sub dvArticulos_ItemInserted(sender As Object, e As EntityDataSourceChangedEventArgs) Handles EntityDataSource1.Inserted
Dim last_Serie As Long = DirectCast(e.Entity, articulos).Serie
Session("Articulo") = last_Serie
End Sub
Related
While working on RESTful service in ASP.NET with support of Entity Framework and SQL Server 2014 as DB engine, I met some unexpected obstacle on my way.
I've prepared some dummy case which exactly explains what kind of problem I'm facing right now.
I've got database in SQL Server named "dummy_database". It contains only one table - Person - and one trigger - TR_Person_Insert - which is responsible for adding some extra data (current date and time in this particular case) to every single record before add the record to the "Person" table. Code of database structure is included below:
USE dummy_database;
GO
IF EXISTS (SELECT * FROM sys.tables WHERE name LIKE 'person')
DROP TABLE [person];
GO
IF EXISTS (SELECT * FROM sys.triggers WHERE name LIKE 'TR_Person_Insert')
DROP TRIGGER [TR_Person_Insert];
GO
CREATE TABLE [dbo].[person]
(
[id] INT IDENTITY(1, 1),
[name] NVARCHAR(256) NOT NULL,
[surname] NVARCHAR(256) NOT NULL,
[age] INT NOT NULL,
[valid_from] DATETIME2 (7),
CONSTRAINT PK_Person_ID PRIMARY KEY ([id])
)
GO
CREATE TRIGGER TR_Person_Insert ON [dbo].[person]
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO [dbo].[person] ([name], [surname], [age], [valid_from])
SELECT i.[name], i.[surname], i.[age], GETDATE()
FROM inserted i
END
GO
Then I created dummy RESTful Service using ASP.NET and added Entity Framework with Database First approach to it. The code of one and only existing method of that Service is as below:
[RoutePrefix("api/person")]
public class DummyController : ApiController
{
[HttpPost, Route("")]
public IHttpActionResult AddPerson(PersonDto data)
{
using (var ctx = new DummyDatabaseModel())
{
var person = new person
{
name = data.Name,
surname = data.Surname,
age = data.Age
};
ctx.people.Add(person);
ctx.SaveChanges();
}
return Ok();
}
}
The problem is with saving changes method called on database's context. This method throws DBUpdateConcurrencyException exception with additional information as below:
An exception of type 'System.Data.Entity.Infrastructure.DbUpdateConcurrencyException' occurred in EntityFramework.dll but was not handled in user code
Additional information: Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded.
I'm aware of the fact that this exception is caused by trigger, which is fired instead of regular 'insert' routine on database's side.
The question I ask is - how to get rid of this kind of exception without abandoning trigger in database. I'm out of ideas and to be frank - I count on your tips or solutions, if you faced same problem in the past.
Thank you for your help.
I had the same problem, in my case, the trigger was the expression "instead of insert"
Ex.
Create trigger TR_AA on TbAA INSTEAD OF INSERT ....
I changed the expression by "AFTER INSERT" It's work for me!
Ex.
Create trigger TR_AA on TbAA AFTER INSERT ....
I wanted to start using Entity Framework for my projects. A new project which we'll be starting soon, will have an Employee table. I was initially planning to have a IEmployee Interface, which will be implemented by a Manager and Staff classes, which will allow different functionality but will both store data in the Employee table, with a flag in the table distinguishing them.
If I use DB First, and design my Employee table and then use Entity Framework, i know the .tt file will have a partial class Employee. I could then make my own Manager and Staff classes which implement the partial class Employee. But then how would I store that back in the db using Entity Framework? Could I just do something like
// currentManager would be the manager object
dbContext.Emplyee.Add(currentManager);
dbContext.SaveChanges();
would entity framework be ok with this, even though i'm passing a Manager object into Employee to save? Or is there a better way to do this? And same with retrieving, how could I use Entity Framework to get back a Manager or Staff? Would I need to get a Employee back first and then cast it? Something like
var employee = from employees... // get employee
Manager currentManager = (Manager)employee;
Yes, you can use EF DB first and have multiple classes derived from a common base class that are stored in the same database table.
The "flag" you envision is called a discriminator by EF. It is a column in the table that specifies which subtype the record is an instance of.
With database first, you need to tweak the model generated by EF to get this working, but it's fairly straightforward. I think the easiest way to set this up is to
Create the database model in SQL, being sure the Employee table has a NOT NULL property like EmployeeType that can be used as the discriminator. I think this can be any type, but an int will work fine.
Create your EF model ( Add | New Item... | Data | ADO.NET Entity Data Model ), and map the Employee table (and anything else you need).
Double click the generated .edmx file to open the entity framework designer.
Right mouse click on the canvass and select Add New... | Entity and create a Manager entity that derives from Employee. Repeat for Staff. Your designer should look like this:
Right mouse click on Manager and select Table Mapping. In the mapping details, specify that it maps to Employee and add a condition that is When EmployeeType = 1. Do the same for Staff, but make the mapping When EmployeeType = 2.
Last, you need to delete the EmployeeType property from the Employee mapping.
That being done, you can extend the Manager and Staff classes (that will now be generated by EF as partial classes) to have whatever business logic you want, and do queries/etc with EF via the Employees mapping:
public class Manager : Employee
{
public void customManagerMethod() { }
}
public class Staff : Employee
{
public void customStaffMethod() { }
}
class Program
{
static void Main(string[] args)
{
using (var db = new dbfirstEntities())
{
Manager m = new Manager
{
FirstName = "Joe",
LastName = "Bigshot"
};
Staff s = new Staff
{
FirstName = "Joe",
LastName = "Schmoe"
};
db.Employees.Add(m);
db.Employees.Add(s);
db.SaveChanges();
}
}
}
When I query from the entity framework I always query in a detached state so that the records retrieved can be stored in cache for subsequent requests.
Right now I have a form that the user can edit which contains a parent record, and then two lists of parent records.
When the data is POSTed to the server, I take my view models and map them into the entity framework objects using AutoMapper. The data looks fine; AutoMapper is mapping the data correctly.
When I attach the object so that I can update it, an exception is thrown: A referential integrity constraint violation occurred: The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship.
public static void UpdateOrder(ShippingOrder shippingOrder) {
using (OrderEntity orderContext = new OrderEntity()) {
//Exception happens here
orderContext.ShippingOrders.Attach(shippingOrder);
//Update the order itself; mark the order has being modified so the EF will update it.
orderContext.ObjectStateManager.ChangeObjectState(shippingOrder, System.Data.EntityState.Modified);
//Perform the update.
orderContext.SaveChanges();
}
}
The EntityFramework (EF) seems to think that my keys aren't lining up, but I'm not sure what isn't correct. The foreign key property does have the correct value, so I'm not sure what it's checking. Does anyone have any ideas?
You might try something like this:
ShippingOrder existingShippingOrder = orderContext.ShippingOrders.Find(shippingOrder.ID);
orderContext.Entry(existingShippingOrder ).CurrentValues.SetValues(shippingOrder);
Instead of
orderContext.ObjectStateManager.ChangeObjectState(shippingOrder, System.Data.EntityState.Modified);
try this
orderContext.Entry(ShippingOrder).State = EntityState.Modified;
as explained here
Insert or update pattern A common pattern for some applications is to
either Add an entity as new (resulting in a database insert) or Attach
an entity as existing and mark it as modified (resulting in a database
update) depending on the value of the primary key. For example, when
using database generated integer primary keys it is common to treat an
entity with a zero key as new and an entity with a non-zero key as
existing. This pattern can be achieved by setting the entity state
based on a check of the primary key value. For example:
public void InsertOrUpdate(DbContext context, Unicorn unicorn)
{
context.Entry(unicorn).State = unicorn.Id == 0 ?
EntityState.Added :
EntityState.Modified;
context.SaveChanges();
}
you can try
public static void UpdateOrder(ShippingOrder shippingOrder) {
using (OrderEntity orderContext = new OrderEntity()) {
orderContext.Entry(shippingOrder).State = shippingOrder.Id==0?
EntityState.Added :
EntityState.Modified;
orderContext.SaveChanges();
}
}
UPDATE:
for ObjectContext class you can try
public static void UpdateOrder(ShippingOrder shippingOrder) {
using (OrderEntity orderContext = new OrderEntity()) {
orderContext.ObjectStateManager.ChangeObjectState(shippingOrder, EntityState.Modified);
orderContext.SaveChanges();
}
}
Im trying to get my head around attaching an entity with a related entity to a new context when I want to update the entity.
I have a Person Table (Generalised to Personnel), which has a LanguageID field. This field is linked as a FK via the EF to another table Language with LanguageID as the primary key (1-M). I need to update a particular Persons language preference, however, the relationship seems to remain linked to the old context as i get a "Object cannot be referenced by multiple instances of IEntityChangeTracker" error on the line marked below. Is there any way to attach the Language entity to the new context as a relationship of the Personnel (Person) entity???
The entities were not detached in the orginal GetPersonnel() method which uses an .Include() method to return the PreferredLanguage
PreferredLanguage is the NavigationProperty name on the Person table...
public static void UpdateUser(Personnel originalUser, Personnel newUser )
{
using (AdminModel TheModel = new AdminModel())
{
((IEntityWithChangeTracker)originalUser).SetChangeTracker(null);
((IEntityWithChangeTracker)originalUser.PreferredLanguage).SetChangeTracker(null);
TheModel.Attach(originalUser);--Error Line
TheModel.ApplyPropertyChanges("Person", newUser);
TheModel.SaveChanges();
}
}
Thanks
Sean
To avoid these sort of problems you should make GetPersonnel() do a NoTracking query.
I.e.
ctx.Person.MergeOption = MergeOption.NoTracking;
// and then query as per normal.
This way you can get a graph of connected entities (assuming you use .Include()) that is NOT attached. Note this won't work if you try to manually detach entities, because doing so schreds your graph.
Hope this helps
Alex
I have a single page which collects related data into a series of input fields.
When the user clicks submit I want to insert the data into two different database tables in one go. ie I want to get the primary key from the first insert, and then use it for the second insert operation.
I am hoping to do this all in one go, but I am not sure of the best way to do this with the Models/Entities in MVC.
Are you using LINQ or some other ORM? Typically these will support the ability to add a related entity and handle the foreign key relationships automatically. Typically, what I would do with LINQtoSQL is something like:
var modelA = new ModelA();
var modelB = new ModelB();
UpdateModel( modelA, new string[] { "aProp1", "aProp2", ... } );
UpdateModel( modelB, new string[] { "bProp1", "bProp2", ... } );
using (var context = new DBContext())
{
modelA.ModelB = modelB;
context.ModelA.InsertOnSubmit( modelA );
context.SubmitChanges();
}
This will automatically handle the insertion of modelA and modelB and make sure that the primary key for modelA is set properly in the foreign key for modelB.
If you are doing it by hand, you may have to do it in three steps inside a transaction, first inserting modelA, getting the key from that insert and updating modelB, then inserting modelB with a's data.
EDIT: I've shown this using UpdateModel but you could also do it with model binding with the parameters to the method. This can be a little tricky with multiple models, requiring you have have separate prefixes and use the bind attribute to specify which form parameters go with which model.