I'm following steven sandersons blogpost on how to make a dynamic list of items on a webpage.
His example doesn't use entity framework however. So far I've been able to store the altered entities, to add newly created entities (I check for an id of 0) but I can't figure out how to delete any removed entities.
Since I only get back the new situation, how can I know what has been deleted?
One way would be to compare the database, and check the id's with what I have gotten back and then delete the ones which didn't came back, but that just sounds like a weird approach.
I also think that approach would fail when there is some kind of paginas going on where you only see a partial representation of the complete data.
Any thoughts on what the postback of the controller would look like?
In such case you can either use AJAX and trigger deletion when the user removes the item or you can use another javascript code which will store Ids of all deleted items to hidden field. When the user finishes the editing and post data back to server you will get those ids from the hidden field and delete those records.
Related
Unable to use AutoMapper in the [HttpPost] Update action method in my controller.
I have Entity tracking fields such as CreatedDate, CreatedBy, ModifiedDate, ModifiedBy and I do not have them as fields in my ViewModel.
When the user posts the form in the Update action method I would typically do something like:
var product = Mapper.Map<Product>(productViewModel);
At this point the tracking fields are null. I can never get them.
It looks like I have two options:
Add the tracking fields to the view model and in the html as hidden fields just like 'Id' so they are posted back to the server.
Instead of creating a new product object, retrieve the product from the database based on viewModel.Id and then manually overwrite all of the values that could have been edited by the user in the form with the viewModels new values.
Does anyone have any additional thoughts or recommendations on this? Step 1 is extra data going to the page that I don't need and Step 2 is an extra database call and unclean code without AutoMapper.
I would use option 2.
Firstly it stops html injections attacks, users could simply edit your html and change fields that you do not intend to expose for edit.
Secondly it's hard to go wrong when editing or adding fields to your base model. You won't have to worry when adding extra properties that you need to carry them over on your viewModel.
Thirdly, unless it's a giant object the database call isn't going to add much delay. Users normally don't mind waiting a little bit more on save operations anyway, makes them feel comfy that the app is actually doing something. :)
I'm quite new to C# MVC so what i'm asking might be bad practice, but is there a way (or should I attempt), to reorder the Ids of the objects in a collection so that the first element always remains with and Id of 1. If it gets deleted and replaced by the second element, this element should then get a new Id of 1.
I'm using Ids to order the displayed elements on a page, and I guess I could manage to create a new property that would serve this purpose, but I'm wondering if reordering the actual Ids would be a good/bad idea.
I'm using Code First, and I let entity manage the Ids automatically for now.
Any advice on the matter will be very welcome!
Thanks in advance!
Yes, you're right in your assumption. Firstly, you should not be using the IDs for sorting. The purpose of the IDs is to identify the records and you should not use them for other purposes. More importantly, it is a very bad idea to change the IDs except in very special cases. When you modify an ID, all related records with foreign IDs referencing the modified IDs need to be changed too.
You are also right that the best way is to add another column called something like "SortingOrder" and use that for your ordering. I do it all the time, and most my tables that need ordering that is decided by the admin have a column called "SortingOrder" (or "sorting_order" in SQL).
When a user hits the button, I'm executing the following code.
using (Context context = new Context())
{
foreach (Thing thing ViewModel.Things)
context.Things.AddOrUpdate(thing);
context.SaveChanges();
}
The updates are executed except for when the user selected a row and hit delete button. Visually, that post is gone but it's not really being removed from the database because it's not in the view model anymore. Hence, the loppification only ticks for the remaining things and not touching the removees.
I can think of two ways to handle that. One really bad - to remove everything from the context, save it and then recreate based on the view model. It's an idiotic solution so I'm only mentioning it for the reference's sake.
The other is to store each removed post in an array. Then, when the user invokes the code above, I could additionally perform the deletion of the elements in that array. This solution requires me to build the logic for that and I'm having this sense that it should be done automagically for me, if I ask nicely.
Am I right in my expectation and if so, how should I do it? If not, is there a smarter way to achieve my goal than creating this kill squad array?
At the moment, I do a double loop, first adding and updating what's left in the data grid. Then, removing anything that isn't found there. It's going to be painful if the number of elements grows. Also, for some reason I couldn't use Where because I need to rely on Contains and EF didn't let me do that. Not sure why.
using (Context context = new Context())
{
foreach (Thing thing in ViewModel.Things)
context.Things.AddOrUpdate(driver);
foreach (Thing thing in context.Things)
if (!ViewModel.Things.Contains(thing))
context.Things.Remove(thing);
context.SaveChanges();
}
The first thing I want to advice you is you should use the AddOrUpdate extension method only for seeding migrations. The job of AddOrUpdate is to ensure that you don’t create duplicates when you seed data during development.
The best way to achieve what you need you can find it in this link.
First in your ViewModel class you should have an ObservableCollection property of type Thing:
public ObservableCollection<Thing> Things {get;set;}
Then in the ViewModel's constructor (or in another place), you should set the Things property this way:
context.Things.Load();
Things = context.Things.Local;
From the quoted link:
Load is a new extension method on IQueryable that will cause the
results of the query to be iterated, in EF this equates to
materializing the results as objects and adding them to the DbContext
in the Unchanged state
The Local property will give you an ObservableCollection<TEntity> that
contains all Unchanged, Modified and Added objects that are currently
tracked by the DbContext for the given DbSet. As new objects enter the
DbSet (through queries, DbSet.Add/Attach, etc.) they will appear in
the ObservableCollection. When an object is deleted from the DbSet it
will also be removed from the ObservableCollection. Adding or Removing
from the ObservableCollection will also perform the corresponding
Add/Remove on the DbSet. Because WPF natively supports binding to an
ObservableCollection there is no additional code required to have two
way data binding with full support for WPF sorting, filtering etc.
Now to save changes, the only you need to do is create a command in your ViewModel class that call SaveThingsChanges method:
private void SaveThingsChanges()
{
context.SaveChanges();
}
Is there a possibility to filter the available values on adding a new record? Please have a look at the following screen:
Each MES_OPERATION is assigned to a MES_ROUTE (both are foreign keys). Now i want to implement that after selecting a MES_ROUTE the list of MES_OPERATIONSs should only show the MES_OPERATIONSs which are assigned to that specific selected MES_ROUTE. Following a screen :
For your understanding: after selecting the route "Daniel" the selectbox of operation should only show the operations which are assigned to the route "Daniel".
What you want to do is called "nested" comboboxes, or "cascading" comboboxes. This can easily be done in a detail screen, but I'm not sure if it's possible in a grid (all my grids are read-only).
Have a look at these two articles, which will explain the technique, & you can see for yourself if it works for a grid.
Nested AutoCompleteBox For Data Entry
Nested AutoCompleteBox for data Entry Part 2
Use ORM systems. If you want the simpliest way then use VS2010 and EntityFramework. It will automatically generate set of classes based on your database and map them. Entity Framework will recognize your PK and FK relations and create collection of Operations inside Route class. Then in code you can use something like this (sorry I don't know tables and database names).
var route = objectSet.Routes.Select(p=>p.Id=="some id").Single();
foreach (var operation in route.Operations)
{
//do your stuff
}
Also you can use other ORM for example NHiberanate. Here are some useful links to get you start:
Simple NHibernate application.
More detailed info about Fluent NHibernate.
I'm trying to delete a child property of a domain entity. In the UI, the user selects Delete to remove a CustomVariableGroup from an Application entity.
I thought deleting the property from the LINQ-to-SQL entity & then submitting changes, would cause LINQ-to-SQL to take care of the work on the Database side. But the row never gets deleted from the table. When I refresh the page in my application, the property is still there because it's still there in the Database.
public void Save(Application application)
{
ApplicationRecord appRecord = application.Map(); // Maps domain entity to L2S entity
// Before this line executes, appRecord has 0 CustomVariableGroups, which is correct.
this.Database.ApplicationRecords.Attach(appRecord, true);
// After the attach, appRecord now has 1 CustomVariableGroup again. This is wrong.
appRecord = application.Map(); // Hack to remove the CustomVariableGroup again.
// This doesn't delete the CustomVariableGroup from appRecord. Do I need
// to delete it explicitly? Or should removing it from appRecord, and
// calling SubmitChanges() do it?
this.Database.SubmitChanges();
}
What is the right way for me to get rid of this child property on the entity? I guess I could loop through the list and delete each item individually, but I don't think LINQ-to-SQL is supposed to work that way.
Any ideas are appreciated.
Note: The property ApplicationCustomVariableGroupRecords represents a table that resolves a many-to-many association in the Database. An Application can have one or more CustomVariableGroups, and a CustomVariableGroup can belong to one or more Applications.
Normally you have to specifically delete the object - removing it from a parent collection just means you don't want it to be associated with that particular parent anymore. It can't tell that you don't want to then associate it with a different parent. If you want it to get deleted, you need to make the call to have it deleted (DeleteOnSubmit for L2S, IIRC)
if im not wrong the tables which have n to n relations between them are works like nested..So try to first delete from the 3rd table (which contains IDs of 2 table) and then remove from main table..
[Sorry, i can't see add comment button on the page.. so i wrote this idea as answer ]