My application allows the user to create products along with their UOM (Units of Measurement) and Barcodes During the creation process, API will check if there is no barcode
I understand. I want to make a strong claim that you should not do what you are trying do using lazy navigation.
I strongly discourage almost all developer use of the Breeze EF context inside a BeforeSave...
method. I'm referring specifically to the EF context that holds your changed barcode
entity.
The Breeze context is reserved for Breeze's own use during the save process. You shouldn't put anything into it that isn't destined for save. That includes entities retrieved by lazy navigation. IMO it is fortunate that you can't navigate.
Why? Security is the most important reason. I can't really trust data from the client. When validating or manipulating client changes, I should get my truth from the database itself.
For the same reason I always ignore the values in the
originalValues
object that came from the client. Never use these values for validation. They are useful primarily for concurrency checking and to help EF figure out the proper save order. TheoriginalValues
property names are important - they tell EF which columns to update - but their values, other than FK and optimistic concurrency property values, are immaterial. Again, don't trust them.
Obviously you have to trust some of the client input ... otherwise you couldn't save anything. But it is wise to limit the scope of that trust to the "safe values" that your validation logic permits this user to create or change.
I fear we have not made these points strongly enough in our documentation.
I am of the firm opinion that you should spin up a new, separate EF context for use in validation and inquiry. That context can be used by other BeforeSave...
activities during the lifetime of the save request.
I populate this read-only EF context directly from the database. I keep it and all of the entities queried into it completely isolated from the Breeze save-context and its change-set entities.
In your case, having created that read-only context, I'd extract the client-supplied barcode
key information and do an expand query to get the related Unit
and Product
information. Then I'd use that information to update the client-supplied barcode
as you've described.
Disagree with me? Nothing stops you from loading the related properties explicitly with the Breeze EF context. You just can't lazy load.
It follows from this that Breeze should not tempt you with lazy loading navigation of the entities in EntityInfos
and should not tempt you into using the Breeze EF context for any purpose other than the preparation of the final collection of entities to be saved.
p.s. Serialization is another reason that lazy load is disallowed. When EF saves changes successfully, Breeze prepares a save result with the saved entities and returns this result to the client. When Json.Net serializes the save result, it wanders down all navigation paths and serializes whatever it finds. If lazy loading were enabled, it would (slowly) pull in tons of related entities from the database and send them too. That is highly undesirable.
p.p.s. Of course we could turn off "lazy load" just before releasing the save result for serialization. But if you had eagerly or lazy loaded the related Unit
and Product
entities into the Breeze EF Context, these too would be serialized and sent to the client in the save result. Not good.
Don't put anything in the Breeze context that isn't supposed to be saved.