I might be not getting how some stuff work in Blazor, but here's what my issue is:
whenever I want to edit an object for example People object, I select it in #page "/people" from a table, then I'm redirected to the #page "people/edit/id". In #page "people/edit" I have an EditForm with InputText corresponding to the people model and the #bind value, everything is normal, it loads the data correctly.
The problem is when I edit some of the inputs and not save the data, just modify its values, and then go back to the #page "people", or anywhere, the object is modified.
I even put a breakpoint to watch the object being pulled from the database through Entity Framework Core, and it shows the modified version too, but checking on the database table, it does not seem to be affected.
It sounds impossible, but I tried with brand new projects, or others people projects in video tutorials, try replicating and does the same thing, so what's the deal here?
#page "/People/edit{id}"
#code {
[Parameter] public string id { get; set; }
Person person = new Person();
protected override async Task OnParametersSetAsync()
{
person = await PersonService.GetByIdAsync(id);
}
}
Firstly, if you put some object as a model for an EditForm and make some changes to it, all changes are reflected in the object immediately, but not after you click a submit.
Secondly, when you pull an object from a database it gets attached to the DbContext and stays attached, unless you detach it explicitly. When you query the entity, already attached to the context, the context does not query the database again, but gives you the attached entity. And if you have made some changes to it, you get these changes.
But those changes are not saved to database until you execute context.SaveChanges, so when you see the actual database, you see the unchanged data.
The difference with Net Core MVC is that Net Core MVC is stateless. Though you use references to the .NET objects in .cshtml files, they are used only during one query and get destroyed after the response is sent to client. When you use Blazor, you get actual .NET runtime ether on server (Blazor server) or on client (Blazor wasm), so your objects remain and preserve their state.
Related
This one is making me crasy : I have an EF model built upon a database that contains a table named Category with 6 rows in it.
I want to display this in a drop down list in WPF, so I need to bind it to the Categories.Local Observable collection.
The problem is that this observable collection never receives the content of the database table. My understanding is that the collection should get in sync with the database when performing a query or saving data with SaveChanges() So I ran the followin 2 tests :
Categories = _db.Categories.Local;
// test 1
Debug.WriteLine(_db.Categories.Count());
Debug.WriteLine(_db.Categories.Local.Count());
// test 2
_categories.Add(new Category() { CategoryName = "test" });
_db.SaveChanges();
Debug.WriteLine(_db.Categories.Count());
Debug.WriteLine(_db.Categories.Local.Count());
Debug.WriteLine(_categories.Count());
The test 1 shows 6 rows in the database, and 0 in local.
The test 2 shows 7 rows in the database, and 1 in local (both versions)
I also atempted to use _db.Category.Load() but as expected, it doesn't work because it is db first, not code first.
I also went through this page https://msdn.microsoft.com/en-us/library/jj574514(v=vs.113).aspx, created an object-based data source and linked my combo box to it, without success.
Does anyone know what I am doing wrong?
Thank you in advance for your help.
The DbSet<T> class is IQueryable<T>, hence DbSet<T>.Count() method maps to Queryable.Count<T> extension method, which in turn is translated to SQL query and returns the count of the records in the database table without loading anything into db context local cache.
While DbSet<T>.Local simply gives you access to the local cache. It contains the entities that you added as well as the ones being loaded by query that returns T instances (or other entities referencing T via navigation property). In order to fully load (populate) the local cache, you need to call Load:
_db.Categories.Load();
The Load is a custom extension method defined in QueryableExtensions class, so you need to include
using System.Data.Entity;
in order to get access to it (as well as to typed Include, XyzAsync and many other EF extension methods). The Load method is equivalent of ToList but without overhead of creating additional list.
Once you do that, the binding will work. Please note that the Local will not reflect changes made to the database through different DbContext instances or different applications/users.
This is a design question.
I'm trying to build a booking system in cakephp3.
I've never done something like this with cake before.
I thought the best way might be to -- as the post title suggests -- build up an entity over several forms/actions.
Something like choose location -> enter customer details -> enter special requirements -> review full details and pay
So each of those stages becomes an action within my booking controller. The view for each action submits its content to the next action in the chain, and i use patch entity with the request data, and send the result to the new action's view.
I've started to wonder if this is a good way to do it. One significant problem is that the data from each of the previous actions has to be stored in hidden fields so that it can be resubmitted with the new data from the current action.
I want the data from previous actions to be visible in a read only fashion so I've used the entity that i pass to the view to fill an HTML table. That's nice and it works fine but having to also store that same data in hidden fields is not a very nice way to do it.
I hope this is making sense!
Anyway, I thought I'd post on here for some design guidance as i feel like there is probably a better way to do this. I have considered creating temporary records in the database and just passing the id but i was hoping I wouldn't have to.
Any advice here would be very much appreciated.
Cheers.
I would just store the entity in the DB and then proceed with your other views, getting data from the DB. Pseudo:
public function chooseLocation() {
$ent = new Entitiy();
patchEntity($ent,$this->request->data);
if save entity {
redirect to enterCustomerDetails($ent[id]);
}
}
public function enterCustomerDetails($id) {
$ent = $this->Modelname->get($id);
// patch, save, redirect again ...
}
I'm getting started with AngularJS with Web API and EF on the back end. I have an edit form that is populated via a GET request which returns a Boat object. One of Boat's properties is an Images array.
If the user adds images to Boat then I need records to be inserted into the database for each new image when the boat is updated. (But obviously not for images that the boat already had prior to edit.)
The current Web API function is:
public async Task<IHttpActionResult> Put(int id, Boat boat)
It seems I could either:
a) Push any newly added images to $scope.Boat.Images prior to the PUT. Then in the Web API function, loop through the received Boat.Images, check if a database record exists for that image, if no record exists add the image record to the database. This seems a bit uneconomical because I'm looping through every existing image and checking if it actually exists in the db already.
or
b) Send a separate object "newImages" with the PUT. Then I guess the Web API function would be:
public async Task<IHttpActionResult> Put(int id, Boat boat, string[] newImages)
This would have the benefit of not having to check which images already exist vs new ones. ie. Everything in newImages gets added to the database. But, is it weird from an AngularJS point of view to separate the new images from the Boat.Images collection?
Would you do a) or b) or... c) some other way?
I'll do A as it fits more the Restful approach.
Now Images could be an Array of complex object instead of Array of string, therefore you would have a property ID.
Then on the WebAPI side, you just add the Images without IDs set.
var newImages = Boat.Images.Select(x => x.Id == null);
I have a simple entity class in a WPF application that essentially looks like this:
public class Customer : MyBaseEntityClass
{
private IList<Order> _Orders;
public virtual IList<Order> Orders
{
get { return this._Orders; }
set {this._Orders = new ObservableCollection<Order>(value);}
}
}
I'm also using the Fluent automapper in an offline utility to create an NHibernate config file which is then loaded at runtime. This all works fine but there's an obvious performance hit due to the fact that I'm not passing the original collection back to NHibernate, so I'm trying to add a convention to get NHibernate to create the collection for me:
public class ObservableListConvention : ICollectionConvention
{
public void Apply(ICollectionInstance instance)
{
Type collectionType =
typeof(uNhAddIns.WPF.Collections.Types.ObservableListType<>)
.MakeGenericType(instance.ChildType);
instance.CollectionType(collectionType);
}
}
As you can see I'm using one of the uNhAddIns collections which I understand is supposed to provide support for both the convention and INotification changes, but for some reason doing this seems to break lazy-loading. If I load a custom record like this...
var result = this.Session.Get<Customer>(id);
...then the Orders field does get assigned an instance of type PersistentObservableGenericList but its EntityId and EntityName fields are null, and attempting to expand the orders results in the dreaded "illegal access to loading collection" message.
Can anyone tell me what I'm doing wrong and/or what I need to do to get this to work? Am I correct is assuming that the original proxy object (which normally contains the Customer ID needed to lazy-load the Orders member) is being replaced by the uNhAddIns collection item which isn't tracking the correct object?
UPDATE: I have created a test project demonstrating this issue, it doesn't reference the uNhAddins project directly but the collection classes have been added manually. It should be pretty straightforward how it works but basically it creates a database from the domain, adds a record with a child list and then tries to load it back into another session using the collection class as the implementation for the child list. An assert is thrown due to lazy-loading failing.
I FINALLY figured out the answer to this myself...the problem was due to my use of ObservableListType. In NHibernate semantics a list is an ordered collection of entities, if you want to use something for IList then you want an unordered collection i.e. a Bag.
The Eureka moment for me came after reading the answer to another StackOverflow question about this topic.
I am having problems saving database records using Linq in visual studio 2010 and sql server 2008.
My problem is that when I am editing some records I sometimes check the original database record for validation purposes, only the original entry seems to be updated in real time - I.e. it is already exactly the same as the edited record, before I have submitted the changes!
Could anyone suggest an effective method of coping with this? I have tried using a 2nd database connection or a 2nd data repository to call the original record from the db but it appears to be already changed when I debug it.
public void SaveobjectEdit(object objectToEdit)
{
object originalObject = GetobjectById(objectToEdit.Id);
if (originalObject.objectStatus != objectToEdit.objectStatus)
{
originalObject.objectStatus = objectToEdit.objectStatus;
}
SaveChanges();
}
The save changes just calls _db.SubmitChanges(); by the way
Has no one got any ideas for the above question?
I hope I was clear - for validation purposes I would like to compare an original database record with one that I am editing. The problem is that when I edit a record and then attempt to retrieve the original record before saving - the original record is exactly the same as the edited record.
If you're trying to retrieve the original record in code, from the same 'context' using the same access method, then it will contain the updated object. Rather than ask why you're doing this or what you're trying to achieve, I'll instead explain how I understand the data context / object context to work (in a very loose and vague fashion).
The context is something like an in-memory representation of your database, where everything is lazy-loaded. When you instantiate the context you're given an object which represents your data model (of course it may not be a 1-1 representation, and can contain various abstractions). Nothing is loaded into the context until necessary; any queries you write stay as queries until you peer in their results. When you access an item (e.g. GetobjectById(objectToEdit.Id)) the item is loaded into the context from the database and you can get and set its properties at your leisure.
Now, the important part: When you access an item, if it has already been loaded into the context then that in-memory object is returned. The context doesn't care about checking changes made; the changes won't be persisted to the database until you submit, but they remain in memory.
The way to refresh the in-memory objects is to call the Refresh method on the context. Try this test:
using (var db = new MyObjectContext())
{
var item = db.Items.First();
item.Name = "testing this thing";
Console.WriteLine(db.Shifts.First().Name);
db.Refresh(System.Data.Objects.RefreshMode.StoreWins, db.Items);
Console.WriteLine(db.Shifts.First().Name);
}
I believe this pattern makes a lot of sense and I'm not sure it could work any other way. Consider this:
foreach (var item in db.Items)
{
item.Name = "test";
}
Assert(db.Items.All(item => item.Name == "test"));
Would you want the Assert to fail? Should those items be reloaded? I don't believe so. I'm looking at the items in my context, not in the database. I'm not checking whether items in the database have been updated, but instead that I've updated all the items in the context of my code.
This is a good reason why I don't use MyObjectContext db - it is not a 'db' or a database connection. It's a context within which I can change whatever I want, so I name it such: MyObjectContext context.