EF CORE: How to modify owned collection on entity - concurrency

I have entity "MyEntity" with a list of owners. Each owner object has 3 properties - Id, type, link.
In the configuration, I am mapping this like owned object.
builder.OwnsMany(a => a.Owner, ownershipBuilder =>
{
ownershipBuilder.HasKey(x => x.Link);
ownershipBuilder.Property(x => x.Id).IsRequired();
ownershipBuilder.Property(x => x.Type)
.HasConversion(t => t.ToString(),
value => (MyType) Enum.Parse(typeof(MyType), value))
.IsRequired();
});
Now, when I try to update this collection of owners, I got DbUpdateConcurrencyException
The flow of update is:
find parent entity by its ID
add owner into the list
call Update method on the dbContext and SaveChanges.
After calling savechanges I got mentioned exception.
Any idea here?
THX.

I solved it,
I am generating Link (Owner entity) in code and this is key in table also. Thus I must use ValueGeneratedNever in the entity configuration.
ownershipBuilder.Property(x => x.Link).ValueGeneratedNever().IsRequired();
Problem solved.

Related

Get name of next doctrine migration

How could I get the name / version of the next migration to execute? Something similar to migrations:latest but more like migrations:next. I need this as input to another command so it needs to be parseable output (can't really just use migrations:status).
You can use the Configuration object of the Doctrine migrations bundle. This is even (somewhat) documented as custom configuration.
Here is a minimal code example that works for me:
public function migrationVersionAction(EntityManagerInterface $em, ParameterBagInterface $parameters) {
$connection = $em->getConnection();
$configuration = new \Doctrine\Migrations\Configuration\Configuration($connection);
$configuration->setMigrationsNamespace($parameters->get('doctrine_migrations.namespace'));
$configuration->setMigrationsDirectory($parameters->get('doctrine_migrations.dir_name'));
$configuration->setMigrationsTableName($parameters->get('doctrine_migrations.table_name'));
return new JsonResponse([
'prev' => $configuration->resolveVersionAlias('prev'),
'current' => $configuration->resolveVersionAlias('current'),
'next' => $configuration->resolveVersionAlias('next'),
'latest' => $configuration->resolveVersionAlias('latest')
]);
}
You might want to set the remaining parameters as well though, especially if they differ from the defaults. For this, the configuration documentation might help in addition to the link above.

how Apollo client optimisticResponse working

http://dev.apollodata.com/react/mutations.html
I am trying out with optimisticResponse, but i am confused... and couldn't get it working on my local.
My questions are:
will optimisticResponse update the props and hence the re-render? how important is __typename: 'Mutation' can you leave it?
updateQueries is for new record appear? is this function trigger automatically or you need to invoke it?
is there any full example of out there which include the apollo server side?
Solution found:
const networkInterface = createNetworkInterface('http://localhost:8080/graphql');
this.client = new ApolloClient({
networkInterface,
dataIdFromObject: r => r.id
}
);
dataIdFromObject is the one thing i am missing during the Apolloclient initiation
dataIdFromObject (Object) => string
A function that returns a object identifier given a particular result object.
it will give unique ID for all result object.

RSpec: undefined method for #<ActionController::TestResponse. Testing a dynamic flash message

I have a simple spec testing the creation of an object of the Baseline class.
it "allows a user to create a baseline score with valid content" do
expect(#user.baselines.count).to eq(0)
#baseline = post(:create, :user_id => #user.id, :baseline => valid_attributes)
expect(response).to redirect_to '/patients/list'
expect(flash[:notice]).to eq("Baseline scores for case #{#baseline.case_id} was successfully created.")
expect(Baseline.all.count).to eq(1)
end
But I get this. I am uncertain where to begin with this - I am uncertain why I can't access the case_id attribute of #baseline.
NoMethodError:undefined method `case_id' for <ActionController::TestResponse:0x007f8f5ab4f3c0>
Just to show...these are the valid attributes
let(:valid_attributes) do {
:dx1 => "IPF",
:dxcon1 => 100,
:db1 => "Progressive",
:dbcon1 => 100,
:mgt=> "Drugs",
:biopsy => "Yes",
:patient_id => #patient.id,
:case_id => #patient.case,
}
end
post doesn't return a model instance it returns a TestResponse object which gives you access to headers, status code, etc. To access the object created as a side effect of calling the :create action you can do Baseline.last (in this case Baseline.first would also work since there are no existing baseline objects)
Also note - if you have an instance variable named #baseline that is assigned in the controller you can access that with assigns(:baseline)
expect(assigns[:baseline]).to be_a(Baseline)

emberjs - dynamic computed property does not trigger classNameBindings

I am creating a mixin to validate components with texFields it looks like this, I am using Ember.defineProperty to create a cp on the fly with a dynamic dependant key:
App.ValidationMixin = Ember.Mixin.create
classNameBindings: ['isInvalid']
input: (e) ->
#_super.apply this, arguments
setup: Ember.on 'didInsertElement', ->
unless validations = #get('validations')
el = #autocompleteElement()
# I had to add this to access the prop rather than it getting
# triggered when the dynamic property changes
if #get('isInvalid')
el.addClass 'is-invalid'
else
el.removeClass 'is-invalid'
validationMixin: Ember.on 'didInsertElement', ->
unless validations = #get('validations')
return
dynamicProperty = # logic to determine dynamic property
Ember.defineProperty this, 'isInvalid', Ember.computed dynamicProperty, 'validator.isSubmitted', ->
# validation logic
The problem is, I have to manually check for this.get('isInvalid') rather then the property function being executed when one of the dependant keys changes.
Can anyone explain why this is?
Ember probably thinks that the property 'isInvalid' is not used anywhere and therefore doesn't update it. I guess that 'didInsertElement' is called after the classNameBindings property... Try to output the 'isInvalid' property in the template to check if that's the case because therefore it must be updated.

Symfony2: File Upload via Doctrine does not fire the PrePersist/PreUpdate lifecycle-event

i tried to implement the file upload via doctrine/lifecycle callbacks as described here:
http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html#using-lifecycle-callbacks
So far it works, but the PrePersist/PreUpdate Event is not fired, the function "preUpload" is not called.
Functions like "upload" and "removeUpload" triggered by other lifecycle events are called correctly.
Does anyone have an idea why the event is not fired or a solution for this problem?
Thanks
I have another solution to this problem:
My entity has a field "updatedAt" which is a timestamp of the last update. Since this field gets set anyway (by the timestampable extension of Gedmo) I just use this field to trick doctrine into believing that the entitiy was updated.
Before I persist the entity I set this field manually doing
if( $editForm['file']->getData() )
$entity->setUpdateAt(new \DateTime());
This way the entity gets persisted (because it has changed) and the preUpdate and postUpdate functions are called properly.
Of course this only works if your entity has a field that you can exploit like that.
You need to change tracking policies.
Full explanation.
there's a much simpler solution compared with changing tracking policies and other solutions:
in controller:
if ($form->isValid()) {
...
if ($form->get('file')->getData() != NULL) {//user have uploaded a new file
$file = $form->get('file')->getData();//get 'UploadedFile' object
$news->setPath($file->getClientOriginalName());//change field that holds file's path in db to a temporary value,i.e original file name uploaded by user
}
...
}
this way you have changed a persisted field (here it is path field), so PreUpdate() & PostUpdate() are triggered then you should change path field value to any thing you like (i.e timestamp) in PreUpdate() function so in the end correct value is persisted to DB.
A trick could be to modify the entity no matter what..on postLoad.
1 Create an updatedAt field.
/**
* Date/Time of the update
*
* #var \Datetime
* #ORM\Column(name="updated_at", type="datetime")
*/
private $updatedAt;
2 Create a postLoad() function that will modify your entity anyway:
/**
* #ORM\PostLoad()
*/
public function postLoad()
{
$this->updatedAt = new \DateTime();
}
3 Just update that field correctly on prePersist:
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function preUpload()
{
$this->updatedAt = new \DateTime();
//...update your picture
}
This is basically a slight variation of #philipphoffmann's answer:
What i do is that i modify an attribute before persisting to trigger the preUpdate event, then i undo this modification in the listener:
$entity->setToken($entity->getToken()."_tmp");
$em->flush();
In my listener:
public function preUpdate(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if ($entity instanceof MyEntity) {
$entity->setToken(str_replace('_tmp', '', $entity->getToken()));
//...
}
}
Another option is to display the database field where the filename is stored as a hidden input field and when the file upload input changes set that to empty so it ends up triggering doctrine's update events. So in the form builder you could have something like this:
->add('path', 'text', array('required' => false,'label' => 'Photo file name', 'attr' => array('class' => 'invisible')))
->add('file', 'file', array('label' => 'Photo', 'attr' => array('class' => 'uploader','data-target' => 'iddp_rorschachbundle_institutiontype_path')))
Path is a property managed by doctrine (equal to the field name in the db table) and file is the virtual property to handle uploads (not managed by doctrine). The css class simply sets the display to none. And then a simple js to change the value of the hidden input field
$('.uploader').change(function(){
var t = $(this).attr('data-target');
//clear input value
$("#"+t).val('');
});
For me, it worked good when I just manually called these methods in the controller.
Do you have checked your metadata cache driver option in your config.yml file?If it exists, just try to comment this line:
metadata_cache_driver: whateverTheStorage
Like this:
#metadata_cache_driver: whateverTheStorage