I'm trying to set deleted() property of TYPO3\CMS\Core\Resource\File and make it actually permanent saving that property on the database.
I need to update my FileReference but is not working, is adding a new image to my record.
So I do:
$fileReference->getOriginalFile()->setDeleted(true);
But then? How is possible to save that into the sys_file table? There is a TYPO3\CMS\Core\Resource\FileRepository but it doesn't have an update() method.
There is a delete() function on \TYPO3\CMS\Core\Resource\File:
$fileReference->getOriginalFile()->delete();
setDeleted() is used internally and is not meant to be public API.
Related
I want to upload a file in Backpack for Laravel and immediately attach the file to the model using Spatie Media Library.
What is my best option to do this?
I tried doing this using the SetImageAttribute mutator as recommended in the docs: https://backpackforlaravel.com/docs/4.1/crud-fields#upload-1
public function setImageAttribute($value) {
$this->addMedia('image');
}
However this method requires me to have an unused "image" field on the DB (because Spatie Media Library uses its own table).
Is there another way to do this without using a mutator/creating extra DB fields?
You can avoid having to create an unused image field on your DB by overwriting both the set and get mutators/accessor on your model.
Laravel documentation defining accessor
Laravel documentation defining mutator
Create the following 2 methods on your model:
public function getImageAttribute()
{
return $this->getFirstMediaUrl('image') ?? '';
}
public function setImageAttribute($file)
{
$this->clearMediaCollection('image'); // to remove any previous files
if ($file) {
$this->addMedia($file)->usingFileName($file->hashName())->toMediaCollection('image');
}
}
If you have a fillable set on your model, also add image to it.
protected $fillable = ['image']
Now you should be able to create and update the files using Backpack.
You may change the implementation based on your needs and requirements.
I'm using js-data (and js-data-angular) in conjunction with sockets via sails.js. When a new item is created/updated via sockets I want to call attention to it in my ui.
I'd like to add an "updated" property to the object, but don't want to inadvertently persist it to the DB.
Is there a way to hang non-persisting properties on a js-data object?
Yes.
You can set this globally on the data store or per-resource by using the omit configuration setting. For instance, when instancing your data store, you can instruct JSData to ignore all properties that begin with an underscore:
var store = new JSData.DS({ omit: [ /^_/ ] });
The documentation for the meta property of the options passed to store.defineResource says:
Put anything you want here. It will never be used by the API.
i want to create one function in edmx which return scaler value,
how to create it in SSDL and how to access it in code?
One problem you have is your SSDL is automatically generated by the 'EntityModelGenerator', so editing it will be wiped out by a rebuild. Your edits need to be done in th EDMX file.
So firstly, you have to decide is (1) your return value a calculation of sorts (i.e. adding values together in the application, rather than at database level), or (2) is it a direct call to a database stored procedure?
(1) First step is to add the function XML definition into your EDMX file:
<Function Name="LineTotal" ReturnType="decimal">
<Parameter Name="lineTotal" Type="MyDbModel.OrderDetail">
<DefiningExpression>
od.Price * od.Quantity
</DefiningExpression>
</Parameter>
</Function>
Now, although your EDMX knows about this function, your IntelliSense won't. So you have to add some code to make this work. It is a best practice to place these functions in a seperate class.
public class ModelDefinedFunctions
{
[EdmFunction("MyDbModel" , "LineTotal")] //Model Name and Function Name
public static decimal LineTotal(OrderDetail od)
{
throw new NotSupportedException("LineTotal cannot be directly used.");
}
}
Entity Framework will know to redirect this function call to the EDMX instead. Any direct call to this method, where the model does not exist will throw an exception.
You can then call it in your LINQ queries like
var productValues = from line in model.OrderDetails
select new
{
od.ProductID,
od.Price,
od.Quantity,
LineTotal = ModeDefinedFunctions.LineTotal(line)
};
(2) If you are adding a stored procedure directly, it is easier to drag and drop it onto the EDMX designer. There is a [FunctionImport()] attribute, but I haven't used it. You can drag and drop and see what code it generates in the EDMX file?
Alternatively, you can call the model.ExecuteCommand(<spname> , params object[] values
) stored procedure execution method.
To facilitate control reuse we created a solution with three separate projects: a control library, Silverlight client, and ASP.NET backend. The control library has no reference to the RIA Services-generated data model classes so when it needs to interact with it, we use reflection.
This has worked fine so far but I've hit a bump. I have a DataGrid control where the user can select a row, press the 'delete' button, and it should remove the entity from the collection. In the DataGrid class I have the following method:
private void RemoveEntity(Entity entity)
{
// Use reflection to remove the item from the collection
Type sourceType = typeof(System.Windows.Ria.EntityCollection<>);
Type genericType = sourceType.MakeGenericType(entity.GetType());
System.Reflection.MethodInfo removeMethod = genericType.GetMethod("Remove");
removeMethod.Invoke(this._dataGrid.ItemsSource, new object[] { entity });
// Equivalent to: ('Foo' derives from Entity)
// EntityCollection<Foo> ec;
// ec.Remove(entity);
}
This works on the client side but on the domain service the following error gets generated during the Submit() method:
"The UPDATE statement conflicted with
the FOREIGN KEY constraint
"********". The conflict occurred in
database "********", table "********",
column '********'. The statement has
been terminated."
One thing I noticed is the UpdateFoo() service method is being called instead of the DeleteFoo() method on the domain service. Further inspection shows the entity is going into the ModifiedEntities ChangeSet instead of the RemovedEntities ChangeSet. I don't know if that's the problem but it doesn't seem right.
Any help would be appreciated, thanks,
UPDATE
I've determined that the problem is definitely coming from the reflection call to the EntityCollection.Remove() method. For some reason calling it causes the entity's EntityState property to change to EntityState.Modified instead of EntityState.Deleted as it should.
Even if I try to remove from the collection by completely circumventing the DataGrid I get the exact same issue:
Entity selectedEntity = this.DataContext.GetType().GetProperty("SelectedEntity").GetValue(this.DataContext, null) as Entity;
object foo = selectedEntity.GetType().GetProperty("Foo").GetValue(selectedEntity, null);
foo.GetType().InvokeMember("Remove", BindingFlags.InvokeMethod, null, foo, new object[] { entity });
As a test, I tried modifying the UpdateFoo() domain service method to implement a delete and it worked successfully to delete the entity. This indicates that the RIA service call is working correctly, it's just calling the wrong method (Update instead of Delete.)
public void UpdateFoo(Foo currentFoo)
{
// Original update implementation
//if ((currentFoo.EntityState == EntityState.Detached))
// this.ObjectContext.AttachAsModified(currentFoo, this.ChangeSet.GetOriginal(currentFoo));
// Delete implementation substituted in
Foo foo = this.ChangeSet.GetOriginal(currentFoo);
if ((foo.EntityState == EntityState.Detached))
this.ObjectContext.Attach(foo);
this.ObjectContext.DeleteObject(foo);
}
I've been researching a similar issue.
I believe the issue is you are calling remove with a reference for an EntityCollections within the DomainContext as the root reference rather than using the DomainContext itself as the root.
So...
ParentEntityCollection.EntityCollectionForTEntity.Remove(TEntity);
Produces the EntityState.Modified instead of EntityState.Deleted
Try instead...
DomainContext.EntityCollectionForTEntity.Remove(TEntity);
I think this will produce the result you are seeking.
Hope this helps.
What is the "column" in the "FOREIGN KEY constraint" error? Is this a field in the grid row and collection that coorosponds to that column? Is it possible that the entity you are trying to remove is a column in the row rather than the row itself which is causing an update to the row (to null the column) rather than to delete the row?
I read your update and looks like you've determined that the problem is the reflection.
Have you tried to take the reflection out of the picture?
As in:
private void RemoveEntity(Entity entity)
{
// Use reflection to remove the item from the collection
Type sourceType = typeof(System.Windows.Ria.EntityCollection<>);
Type genericType = sourceType.MakeGenericType(entity.GetType());
// Make sure we have the right type
// and let the framework take care of the proper invoke routine
if (genericType.IsAssignableFrom(this._dataGrid.ItemsSource.GetType()))
((Object) this._dataGrid.ItemsSource).Remove(entity);
}
Yes, I know it's ugly, but some times...
Edited to add
I've updated the code to remove the is keyword.
Now about using the object to make the call to the Remove method, I believe it might work due the late binding of it.
I have a Recommendation object and a FeedbackLevel object and the FeedbackLevel object is a navigation property inside a Recommendation object
Recommendation
int EntityKey;
FeedbackLevel Level;
Inserting a new one works just fine with AddObject(). Here's what I'm trying with the update, which doesn't work.
recommendation.Level = myRepository.GetFeedbackLevel(newLevel);
_context.Recommendations.Attach(new Recommendation { EntityKey = recommendation.EntityKey });
_context.Recommendations.ApplyCurrentValues(recommendation);
_context.SaveChanges(System.Data.Objects.SaveOptions.AcceptAllChangesAfterSave);
The code above is basically a compact version of what I have. Updating a scalar property works just fine, but I can't update a new navigation property as the avove code succeeds without any changes!
I've also tried a few other methods like getting an existing Recommendation first and then re-assigning the FeedbackLevel to it without any luck.
UPDATE:
Here is what I captured from the sql profiler during the save call:
exec sp_executesql N'update [dbo].[Recommendation]
set [FeedbackComment] = #0, [LastUpdatedDate] = #1
where ([RecommendationKey] = #2)
',N'#0 varchar(255),#1 datetime,#2 int',#0='This is cool',#1='2010-01-08 10:06:06.5400000',#2=11
It looks like it does not even know that the FeedbackLevel needs to be saved. How can I get it to trigger it?
Not sure exactly what your trying to do here,
but if your trying to do an update, simple way is to
1) do a, GET [entityName] by id, use include to get any child properties
2) update the attributes
3) make sure the entity state is modified
4) Save changes
By doing a GET first, you wont need to get attach it to the context before you update, as it will be already in there.