I've learned that entities are classes that represent the tables inside a database schema. But on this link they speak of an entity being tracked (attached) by the context
http://msdn.microsoft.com/en-us/data/jj592676.aspx
Added: the entity is being tracked by the context...
Do they speak of the objects/instances of entity's (so the classes) getting tracked by Entity Framework? Or literally the entity itself? I'm confused.
In one of my webapplications I am using this code, does it say all instances of FinalStudyDecision are in the modified state, or just the object fsd?
context.FinalStudyDecisions.Attach(fsd);
context.Entry(fsd).State = EntityState.Modified;
Or does this code just do it for one single object?
ObjectStateManager.ChangeObjectState(fsd, EntityState.Modified);
When an entity is attached to a context, the context "knows" the object and starts tracking its changes.
Normally, an entity is attached to a context when it is fetched from the database, e.g. by context.FinalStudyDecisions.Single(x => x.Id == 1) (if there is an item with Id == 1 of course).
But if you've got an existing FinalStudyDecisions that is not known by a context you can use the Attach method to make it known. This usually happens when an object is serialized to and subsequently deserialized from a web client.
If you attach an object to a context its state (EntityState) is Unchanged, so often you will change its state to Modified when you receive it back from a web client. This will trigger EF to store the object when SaveChanges is called.
Both
// DbContext API
context.Entry(fsd).State = EntityState.Modified;
and
// ObjectContext API
ObjectStateManager.ChangeObjectState(fsd, EntityState.Modified);
only change the state of the fsd object.
Important: if you Add an object to a context, either by setting its state Added or by adding it to a DbSet (or ObjectSet), not only fsd but also all its child objects are changed to Added.
Related
I use the repositoryFactory in a custom plugin's Vue file in Shopware 6. When I save an entity I do this:
this.settingsRepository
.save(this.setting, Shopware.Context.api)
.then((result) => {
In case the person sends the form and this function is called, I want to get back the id of the setting in case the person hit's the save button again. But then the entity needs to be updated and not created. As I see from the response, there is an id, but it's in config.data -> json serialised.
How's the default way of solving this issue?
The best practice would be to re-fetch the entity after persisting it. This is because some entities may have fields that get automatically computed or indexed server-side and you'd probably always want to have the entity in its actual current state. If you're absolutely sure you don't want to fetch the entity again, you could manually set the _isNew flag to false after persisting:
this.setting._isNew = false;
This will then cause the save function to use the update instead of the create route. Keep in mind that this is actually kind of an internal property, as there is no setter for it and as already mentioned fetching the entity again is encouraged.
Also you shouldn't have to worry about the id. It should've already been generated client-side and set to the entity, when using the repository to create a new entity like that:
this.setting = this.settingsRepository.create();
I'm using AFIncrementalStore to connect my iOS application to my REST API. When I load my initial view controller, I create an NSFetchRequest that loads the latest 100 Events (NSManagedObjects) into view. The problem is that each Event has a 1:1 relationship with a Group object, and as soon as the Event is loaded, the incremental store is asked to fill that Group object, which in my case triggers an individual request to the server for each of the 100 Events.
I can see a couple ways to solve this problem, such as not requesting Groups from the server if they are already saved locally, caching the network request, or not storing the relationship in the NSManagedObject. But ideally, the Group object could start out as a Fault and only request to be filled once one of its field is accessed, similar to what happens with one-to-many relationships. Unfortunately I can't find any documentation that says how to force a one-to-one relationship in core data to be lazy-loaded. Is it possible?
Maybe this is what you are looking for?
From AFIncrementalStore.h:
/**
Returns whether the client should fetch remote relationship values for a
particular managed object. This method is consulted when a managed object
faults on a particular relationship, and will call
`-requestWithMethod:pathForRelationship:forObjectWithID:withContext:` if `YES`.
#param relationship The relationship of the specifified managed object
#param objectID The object ID for the specified managed object.
#param context The managed object context for the managed object.
#return `YES` if an HTTP request should be made, otherwise `NO. */
- (BOOL)shouldFetchRemoteValuesForRelationship:(NSRelationshipDescription*)
relationship forObjectWithID:(NSManagedObjectID *)objectID
inManagedObjectContext:(NSManagedObjectContext *)context;
If so, you could set this with
- (BOOL)shouldFetchRemoteValuesForRelationship:(NSRelationshipDescription *)relationship forObjectWithID:(NSManagedObjectID *)objectID inManagedObjectContext:(NSManagedObjectContext *)context
{
return NO;
}
in your AFRESTClient <AFIncrementalStoreHTTPClient> subclass.
I've been struggling this as well. Looks like one-to-one relations will always be eager loaded. One way around this could be to declare it as a one-to-many relation so that it automatically does a lazy load instead. Then in your model class, you can have a method that returns the first one in the set.
I'm designing my first project using Core Data (for iPhone) and Im having some issues that might be related with my design approach.
I'm doing an application that allows the user to create an Order (let's say for a restaurant).
I'm using the graphic designer to model my persistence object (i.e. OrdeMO). I add MO to the ead of each name to indicate its a Managed Object.
I use XCode to create the Managed Object Class automatically.
I have created some "DAO" classes that allows you to search or create a new object in the Managed Context.
Now to my problem.
I want to create an OrderMO object to store the order the user is creating, BUT I don't want it to be part of the context until the user actually places it.
I tried creating the object with [OrderMO alloc] but the object I get is "incomplete" and when I try to set any of its attribute I get an error.
I'm assuming the problem is that I need to create the order IN the context in order to use it. Is that so?
I have considered various options:
Create the object in the context and the user rollback if the user discards the order. The problem is that the user might save other context object during the process (like his prefs) so this doesn't work. Is there a way to create the object "inside a separate transaction" of sorts?
Create a wrapper object that will hold the same data as the MO, and then only create the MO when the user place the order. The downside of this is that I have to maintain a new class.
Create an attribute in the MO, such as "placed", and use to filter my searches in the context. The problem with this one is that I will end up with "trash" objects in the domain (i.e. unplaced orders) and I will have to do some cleanup from time to time...
Do I have any other choice?
Any suggestion is appreciated.
Thanks (for reading this long post!)
Gonso
You should create the OrderMO object in the managed object context and then delete it if the user decides not to place the order.
If the context is saved before the object is deleted, the "trash" object will be deleted from the persistent store on the next save (if the context wasn't saved, the "trash" object will never be saved to the persistent store).
The flag to determine if the order was placed or not does not have to live in the OrderMO object as you suggest in option 3. It could be in the view controller that is tracking the order(s) that are being edited. And, again, you won't have "trash" objects because they will have been deleted.
I have a fairly straight-forward sequential approval workflow that has an EnableModificationActivity that is in scope for just about the entirety of the workflow. My modification form is an ASPX page that gives the user the ability to enable/disable approval steps that have not occurred yet in the workflow. Since the workflow is able to be modified multiple times, I would like to the form to reflect the current state of the workflow, meaning it should show which activities are currently enabled or disabled.
I have come up with a clunky solution for this that I will share a little later on, but I have got to believe there is a clean way to go about this.
So here is the approach I ended up taking...
I created a Plain Old CLR Object (POCO) class specific for holding state information my particular workflow that is capable of being XML Serialized. I'll call this the "State Object" going forward.
I created a reusable class called "WorkflowStateManager" that is capable of loading and saving single State Objects for a given SPWorkflow. This class is accessible by both the workflow and the modification form.
Save State Implementation:
XML serializes the object to a string
Sets the serialized string on the SPWorkflow list item's property bag and calls the property bag's Update() method
Load State Implementation (Essentially the reverse of the Save State implementation)
Gets the serialized string from the SPWorkflow list item's property bag
XML Deserialize the string into the State Object
When the workflow is activated, I construct a new State Object, initialize various properties on it, and save it using the WorkflowStateManager.
As the workflow progresses, I load and update the State Object as needed in the following manner:
Use the WorkflowStateManager to load the current State Object
Make workflow decisions based on the State Object's values
Make desired changes to the State Object
Use the WorkflowStateManager to save the State Object
Now, my modification form is also able to load, manipulate, and save the State Object using the WorkflowStateManager, and in turn expose the current state of the workflow to the user.
I hope this might be of benefit to someone.
I want to follow the DDD philosophy and not access entity objects of an aggregate directly. So, i have to call the root object to get the associated entity. But In other cases I dont always want every associated entity to load when the root is called. Is that the purpose of lazy loading?
How do I access entity objects through the root without loading all the associated objects everytime if i disable lazyloading feature of linq?
EDIT:
For example, If I have a Person as the Root Entity, and the Person has Name, Addresses and OwnedProperties. If I want to get a list of People so that I could display their names, I dont necvessarily want to load up Owned Properties every time on the call to the Repository. Conversely, on another page I may want to show a list of OwnedProperties, but do not want the other information to load with the call. what is the simple way of just calling the Person without the owned property entity other than creating a new person object without that owned properties?
I don't thinks that's possible without lazy loading.
Getting all data at once: Eager Loading
Getting data when accessed: Lazy Loading
According to your edit:
What I do in these situations, is create a 'View' class or a 'DTO' class which just contains the properties that I'm interested in.
For instance, I could have a 'PersonView' class which just has a Name property for instance.
Then, using my OR/M mapper (I use NHibernate), I create a HQL query (or Criteria query) which works on my 'Person' entity. Before I execute the query, I tell NHibernate that I want 'PersonView' objects as a result (I specify a projection). Then, NHibernate is smart enough to execute a query that only retrieves the columns that are necessary to populate the PersonView instances.
One way to avoid lazy loading is just using the object 'id'