I searched on many site about savechanges but i dont get any proper
answer can any one tell me about
db.SaveChanges()
ModelState
db.SaveChanges() is not part of ASP.NET MVC - it's part of Entity Framework which is a set of Object-Relational-Mapping (ORM) tools for the .NET Framework. All this method does is persist (save) data in some of your classes (entities) into a database.
Useful links:
Scott Gu - Code-First Development with Entity Framework 4
MSDN - Entity Framework
ModelState is a part of MVC and allows extra binding metadata to be passed from the Controller to the View, which is typically largely about validation.
Useful links:
MSDN - Model State Class
MSDN - Performing Simple Validation
msdn says : It persists all updates to the data source and resets change tracking in the object context.
Example
To save the changes made to the entities to a database, we need to call the ObjectContext class SaveChanges method. In the example given below, the query retrieves the first customer from the entityset -Customer.
var customer = context.Customer.First();
The context.Customer returns the Objectset of Customer types and the LINQ extension method First() returns only the first customer.
customer.FirstName = "Yasser";
customer.LastName = "Shaikh";
context.SaveChanges();
We can edit the first customer details like name and address by assigning new values to the properties and call the SaveChanges() method to save the changes back to the database.
During SaveChanges, the ObjectContext determines which fields were changed. In this example, only FirstName and LastName are changed. So, only those two values are sent into the command. To identify the row to be updated in the database, the ObjectContext uses the value of the EntityKey property.
Please read:
http://msdn.microsoft.com/en-us/library/bb336792(v=vs.110).aspx
http://www.asp.net/mvc/tutorials/older-versions/models-(data)/performing-simple-validation-cs
This should help you a little. Basically the db.SaveChanges() method is used by Entity Framework to save current changes to the database and ModelState represents validation errors when e.g. the model is not valid.
Related
I'm new to Spring, Spring data and Spring MVC so I want to make sure I am not missing something.
I have a form for updating a User object, the form posts to a controller and the controller calls my service class that updates/add the entity using a UserDOA which extends CRUDRepository. I think this is a very basic test code.
The issue is that the form doesn't contain all the fields in my User class, so when the object is posted to the controller, only the fields that are contained in the form are populated and the entity fields that are not in the form are null. For example my user has 4 fields, firstname, lastname, age, password. The form only contains the first 3 fields so when the object is posted to the controller, the password field is null, that is as I expect. My issue is that if I then call save(entity) on my DAO it will update the user but that would include nulling the password field, which of course is undesirable.
Of course I could simply retrieve the original entity from the repository and merge it with only the fields that have been updated, but it seems to me this is a lot of work that would be very commonly required and typically spring has a solution to these types of generic tasks.
Did I miss something?
TIA
I've got a WebAPI OData controller which is using the Delta to do partial updates of my entity.
In my entity framework model I've got a Version field. This is a rowversion in the SQL Server database and is mapped to a byte array in Entity Framework with its concurrency mode set to Fixed (it's using database first).
I'm using fiddler to send back a partial update using a stale value for the Version field. I load the current record from my context and then I patch my changed fields over the top which changes the values in the Version column without throwing an error and then when I save changes on my context everything is saved without error. Obviously this is expected, the entity which is being saved has not been detacched from the context so how can I implement optimistic concurrency with a Delta.
I'm using the very latest versions of everything (or was just before christmas) so Entity Framework 6.0.1 and OData 5.6.0
public IHttpActionResult Put([FromODataUri]int key, [FromBody]Delta<Job> delta)
{
using (var tran = new TransactionScope())
{
Job j = this._context.Jobs.SingleOrDefault(x => x.JobId == key);
delta.Patch(j);
this._context.SaveChanges();
tran.Complete();
return Ok(j);
}
}
Thanks
I've just come across this too using Entity Framework 6 and Web API 2 OData controllers.
The EF DbContext seems to use the original value of the timestamp obtained when the entity was loaded at the start of the PUT/PATCH methods for the concurrency check when the subsequent update takes place.
Updating the current value of the timestamp to a value different to that in the database before saving changes does not result in a concurrency error.
I've found you can "fix" this behaviour by forcing the original value of the timestamp to be that of the current in the context.
For example, you can do this by overriding SaveChanges on the context, e.g.:
public partial class DataContext
{
public override int SaveChanges()
{
foreach (DbEntityEntry<Job> entry in ChangeTracker.Entries<Job>().Where(u => u.State == EntityState.Modified))
entry.Property("Timestamp").OriginalValue = entry.Property("Timestamp").CurrentValue;
return base.SaveChanges();
}
}
(Assuming the concurrency column is named "Timestamp" and the concurrency mode for this column is set to "Fixed" in the EDMX)
A further improvement to this would be to write and apply a custom interface to all your models requiring this fix and just replace "Job" with the interface in the code above.
Feedback from Rowan in the Entity Framework Team (4th August 2015):
This is by design. In some cases it is perfectly valid to update a
concurrency token, in which case we need the current value to hold the
value it should be set to and the original value to contain the value
we should check against. For example, you could configure
Person.LastName as a concurrency token. This is one of the downsides
of the "query and update" pattern being used in this action.
The logic
you added to set the correct original value is the right approach to
use in this scenario.
When you're posting the data to server, you need to send RowVersion field as well. If you're testing it with fiddler, get the latest RowVersion value from your database and add the value to your Request Body.
Should be something like;
RowVersion: "AAAAAAAAB9E="
If it's a web page, while you're loading the data from the server, again get RowVersion field from server, keep it in a hidden field and send it back to server along with the other changes.
Basically, when you call PATCH method, RowField needs to be in your patch object.
Then update your code like this;
Job j = this._context.Jobs.SingleOrDefault(x => x.JobId == key);
// Concurrency check
if (!j.RowVersion.SequenceEqual(patch.GetEntity().RowVersion))
{
return Conflict();
}
this._context.Entry(entity).State = EntityState.Modified; // Probably you need this line as well?
this._context.SaveChanges();
Simple, the way you always do it with Entity Framework: you add a Timestamp field and put that field's Concurrency Mode to Fixed. That makes sure EF knows this timestamp field is not part of any queries but is used to determine versioning.
See also http://blogs.msdn.com/b/alexj/archive/2009/05/20/tip-19-how-to-use-optimistic-concurrency-in-the-entity-framework.aspx
mvc 4 using sql server 2008, code first, ef5
I have a ViewModel associated with a view.
As a starting point I'm modifying the scaffolding created by VS.
I can populate the form fine.
When the user clicks save - this is the code in the scaffolding:
[HttpPost]
public ActionResult Edit(Place place)
{
if (ModelState.IsValid)
{
db.Entry(place).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(place);
Place is a model. I need to pass a viewmodel (including place) back to this.
How do I persist the viewmodel in the database using EF? Do I have to split it into models first?
When I try that I get this error:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
When I debug it also seems the PlaceID (from model) is missing from the model that's passed back to the controller httpPost Edit controller - maybe that's the source of the error?
Are there any examples of best practice online for this - I can't find anything.
Thanks.
How do I persist the viewmodel in the database using EF?
You do not persist view models in a database. They role is not to be persisted. View models are used to define the logic used by your view. It is inside your controller action that you could map the view model back to your domain model that will be persisted using the data access technology of your choice. You could use AutoMapper to map between your view models and domain models.
When I debug it also seems the PlaceID (from model) is missing from
the model that's passed back to the controller httpPost Edit
controller - maybe that's the source of the error?
Yes, that's the possible reason. If you want to update some record in the database EF need to know which is this record using the ID.
This was missing in the View:
#Html.HiddenFor(model => model.place.PlaceID)
This keeps tabs on the ID of the model
I am trying my hands on MVC 2, ADO.NET EF and POCO. I have generated my entity classes in a separate library using POCO generator.These POCO entities are used as ViewPages (Not sure if that's the right way to design or do I need separate ViewModels classes ?)
Now, if I take case of a simple scenario where I need to add an Employee object( which is related to a Department Master), what then should be the recommended way to transfer these objects between layers.
Layered structure of the application is somewhat like this :
I have thought of various alternatives:
I have a method in the Employee Controller which is named AddEmployee() which accepts the FormCollection as parameter. Within the form collection I get posted data such as Employee Name, Age , Salary etc and the ID of the Selected Department .
1.) One way is that I can create another DTO say EmployeeDepartment DTO which will be used to map values from FormCollection as is. I can then break them at manager layer and use them to create entity objects i.e Employee Object and refer department by query similar to this:
e.Department = Department.where(i => i.deptId == empDepDto.dept_id).first()
I am not a big fan of this and feel that every time there is a relation involved I have to add a DTO and then map it to my entity class.
2.) Second is probably the worst, i.e passing each object as parameter and then couple them in manager layer.
3.) Use POCO as is, Create a Employee Object and Deparment Object at controller layer and pass the POCO object
public void AddEmployee(FormCollection formCollection)
{
Department d = new Deparmtent; d.id = ""; //based on the dropdown value
d.name="" //based on the dropdown selected text;
Employee e = new Employee; e.Name. e. sal....
e.Department = d;
EmployeeManager.AddEmployee(e);
}
But at manager layer I think , I still need to recreate the reference to the Department using LINQ which again is repetitive and doesn't seems to be a clean solution.
Are there better ways of handling this ? Looking for recommendations and best practices.
Firstly, is there any reason you're not using MVC version 3? There's no major breaking changes, so may as well upgrade?
Secondly is there a reason for using FormCollection rather than the strongly typed model-binding? Just change your views to use the strongly typed HTML helpers ( like <%: Html.TextBoxFor(m => m.Property) %>), or make sure the name attributes match the property names, and have your controller receive the type, and model binding will do the rest. There's plenty of tutorials showing this, and articles explaining it. Model binding will work with a name/value collection, like that posted as a form, or against JSON data, or you can find/write custom model binders that work against whatever wacky serialisation protocol you want.
One thing to watch though when passing the actual entity types that Entity Framework will store around, is that you have to be careful when updating existing objects, or with foreign key references to existing objects - all your objects must be attached to the right Entity Framework context. To achieve that you will often see the objects received by the controller having their properties copied to a freshly retrieved entity from a context, either manually or by an object mapper of some kind.
Make a seperate project called "BusinessObjects" or "Model" which contains your POCOs. Then use strongly typed model-binding for MVC and you'll be set.
The method signature will look something like this:
// In your Controller
public void AddEmployee(Employee newObject)
{
YourDataContext dc = new YourDataContext();
dc.Employees.Add(newObject);
dc.SaveChanges();
}
I am using EF 4.3 in an ASP.NET WebForms application. I've started with model first approach with context object of type ObjectContext and POCO code generator (via T4).
At the beginning the Context was created at the beginning of every service method. While working on performance I decided to switch to context per web request. Unfortunately I have encountered an issue with Table-per-Type inheritance. I have two entities: Offer and OfferEdit. They are in a one to one relationship, and both share the same primary key. Basically an OfferEdit (OfferEdits table) is created once an Offer is being edited.
I query the context for a particular Offer entity more then once during web request. The error I get trying to execute:
var offer = Context.Offer.Where(o => o.Id == offerId).FirstOrDefault()
when this offer is already loaded to Context.Offer.EntitySet is
All objects in the EntitySet 'RuchEntities.Offer' must have unique primary keys.
However, an instance of type 'Ruch.Data.Model.OfferEdit' and an instance of type'Ruch.Data.Model.Offer' both have the same primary key
value,'EntitySet=Offer;Id=4139'.
Will appreciate all advice.
Sounds like you are misusing TPT inheritance. To make it clear EF inheritance works exactly same way as in .NET - the entity can be either of type Offer or OfferEdit. You can convert OfferEdit to Offer but it is still OfferEdit. It can never be of both types which means you can never have Offer entity with Id same as OfferEdit entity because same key cannot be used by two entity instances. You also never can change instance of Offer to OfferEdit because .NET doesn't allow you changing type of existing instance.