I'd like to "duplicate" an ORM object and then save it into the database (with a new primary key), but I am not able to unset the primary key of the copied object.
$orm1 = new Model1($id);
if($orm1->loaded()) {
$orm2 = $orm1;
$orm2->id = null; //something like this?
unset($orm2->_primary_key); //or like this?
$orm2->save(); //I would like to create a new entry in the db but it doesn't work
}
I hope I am clear enough... Basically, how can I "save again" a model in the db...?
You need to copy ORM data from one model to another:
// save current data
$data = $orm1->as_array();
$orm2 = new Model1();
$orm2->values($data);
$orm2->save();
This example uses separate ORM objects. You can load values back to $orm1, but don't forget to call $orm1->clear() before $orm1->values($data). This resets the model to its unloaded state.
Note that as_array will also return belongs_to relationships.
You might want to try this:
// Reset primary key
$this->_primary_key_value = NULL;
And do not forget about Object cloning: Object Cloning
Related
I can successfully add and fetch values from my firebase database.
firebase.initializeApp(config);
// Get a reference to the database service
var database = firebase.database();
var ref = database.ref();
var refer = database.ref('todo');
I have a todo list in my database, I wanted use an array but from what I understand firebase doesnt prefer arrays.
So I just add values to my todo list like
function handleAddTodoIntent(intent, session, response) {
refer.push(todoSlot.value);
}
and it works
But when I try to remove the items , it seems it doesnt do anything
refer.remove(); removes entire todo dictionary and refer.child(todoSlot.value).remove(); seems not deleting the value from database.
What is the correct way of doing this?
Your mistake is refer.child(todoSlot.value).
You are referencing the wrong path. child() should take the name of the field, not a value.
When you push a new child, you can get its key by following:
var todoSlotKey = refer.push(todoSlot.value);
And if you just want to remove the pushed todoSlot.value, you can simply do: refer.child(todoSlotKey).remove();
I'm trying to use a background task to gather Likes/Comments from the Facebook Graph APi and use that to drive our blog's trending.
Here the trendingModels have already been populated and are being used to fill in the TrendingParts.GraphId and TrendingParts.TrendingValue.
I'm not getting any exceptions and the properties on TrendingPart point to the fields in the TrendingPartRecord.
Yet nothing persists to the database, any ideas why?
_orchardsServices is IOrchardServices
var articleParts = _orchardService.ContentManager.GetMany<TrendingPart>(
trendingModels.Select(r => r.OrchardId).ToList(),
VersionOptions.Published,
QueryHints.Empty);
// Cycle through the records and update them from the matching model
foreach (var articlePart in articleParts)
{
ArticleTrendingModel trendingModel = trendingModels.Where(r => r.OrchardId == articlePart.Id).FirstOrDefault();
if(trendingModel != null)
{
// Not persisting to the database, WHY?
// What's missing?
// If I'm understanding things properly nHibernate should push this to the db autoMagically.
articlePart.GraphId = trendingModel.GraphId;
articlePart.TrendingValue = trendingModel.TrendingValue;
}
}
Edit:
It's probably worth noting that I can update and publish the fields on the TrendingPart in the admin panel but the saved changes don't appear in the MyModule_TrendingPartRecord table.
The solution was to change my Service to a transient dependency using ITransientDependency.
The service was holding a reference to the PartRecords array and because it was treated as a Singleton it never disposed and the push to the database was never made.
Hi guys can anyone shed some light on how to do this please.
I have a userRecord object with various sub-objects in including things like their skills-sets, contracts etc.
I get the record by querying the store for the userId as below.
var userRecord = userStore.findRecord('id', userId);
Next I have a variety of forms with checkboxes in a tabpanel relating to each of the user's sub-objects e.g. Skillsets and Contracts. I am trying to overwrite these on the userRecord with an array on checkboxes that have been checked.
var skillsetCheckBoxes = skillsetPanel.query('checkboxfield[checked=true]');
var skillsets = new Array();
Ext.each(skillsetCheckBoxes, function (skillset)
{
console.log(skillset);
skillsets.push(skillset);
});
I have tried to set the userRecord's engineer's skillset object to be the new array:
userRecord.set(('engineer').skillsets, skillsets);
But when I log the record after doing this it is still the same record I retrieved from findRecord() with no edited fields.
Any help much appreciated,
Thanks!
Hard to say without knowing your model's structure, but your line is clearly wrong. You are using ('engineer').skillsets as the key argument for the set method. Since it's not a string but an array, it won't do anything good.
Your line should rather be something like that:
// You should probably test that there is something in there, or the
// next line could crash...
var engineer = userRecord.get('engineer');
if (engineer) {
userRecord.get('engineer').skillsets = skillsets;
}
I am using Entity Framework 5 (DBContext) and I am trying to find the best way to deep copy an entity (i.e. copy the entity and all related objects) and then save the new entities in the database. How can I do this? I have looked into using extension methods such as CloneHelper but I am not sure if it applies to DBContext.
One cheap easy way of cloning an entity is to do something like this:
var originalEntity = Context.MySet.AsNoTracking()
.FirstOrDefault(e => e.Id == 1);
Context.MySet.Add(originalEntity);
Context.SaveChanges();
the trick here is AsNoTracking() - when you load an entity like this, your context do not know about it and when you call SaveChanges, it will treat it like a new entity.
If MySet has a reference to MyProperty and you want a copy of it too, just use an Include:
var originalEntity = Context.MySet.Include("MyProperty")
.AsNoTracking()
.FirstOrDefault(e => e.Id == 1);
Here's another option.
I prefer it in some cases because it does not require you to run a query specifically to get data to be cloned. You can use this method to create clones of entities you've already obtained from the database.
//Get entity to be cloned
var source = Context.ExampleRows.FirstOrDefault();
//Create and add clone object to context before setting its values
var clone = new ExampleRow();
Context.ExampleRows.Add(clone);
//Copy values from source to clone
var sourceValues = Context.Entry(source).CurrentValues;
Context.Entry(clone).CurrentValues.SetValues(sourceValues);
//Change values of the copied entity
clone.ExampleProperty = "New Value";
//Insert clone with changes into database
Context.SaveChanges();
This method copies the current values from the source to a new row that has been added.
This is a generic extension method which allows generic cloning.
You have to fetch System.Linq.Dynamic from nuget.
public TEntity Clone<TEntity>(this DbContext context, TEntity entity) where TEntity : class
{
var keyName = GetKeyName<TEntity>();
var keyValue = context.Entry(entity).Property(keyName).CurrentValue;
var keyType = typeof(TEntity).GetProperty(keyName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).PropertyType;
var dbSet = context.Set<TEntity>();
var newEntity = dbSet
.Where(keyName + " = #0", keyValue)
.AsNoTracking()
.Single();
context.Entry(newEntity).Property(keyName).CurrentValue = keyType.GetDefault();
context.Add(newEntity);
return newEntity;
}
The only thing you have to implement yourself is the GetKeyName method. This could be anything from return typeof(TEntity).Name + "Id" to return the first guid property or return the first property marked with DatabaseGenerated(DatabaseGeneratedOption.Identity)].
In my case I already marked my classes with [DataServiceKeyAttribute("EntityId")]
private string GetKeyName<TEntity>() where TEntity : class
{
return ((DataServiceKeyAttribute)typeof(TEntity)
.GetCustomAttributes(typeof(DataServiceKeyAttribute), true).First())
.KeyNames.Single();
}
I had the same issue in Entity Framework Core where deep clone involves multiple steps when children entities are lazy loaded. One way to clone the whole structure is the following:
var clonedItem = Context.Parent.AsNoTracking()
.Include(u => u.Child1)
.Include(u => u.Child2)
// deep includes might go here (see ThenInclude)
.FirstOrDefault(u => u.ParentId == parentId);
// remove old id from parent
clonedItem.ParentId = 0;
// remove old ids from children
clonedItem.Parent1.ForEach(x =>
{
x.Child1Id = 0;
x.ParentId= 0;
});
clonedItem.Parent2.ForEach(x =>
{
x.Child2Id = 0;
x.ParentId= 0;
});
// customize entities before inserting it
// mark everything for insert
Context.Parent.Add(clonedItem);
// save everything in one single transaction
Context.SaveChanges();
Of course, there are ways to make generic functions to eager load everything and/or reset values for all keys, but this should make all the steps much clear and customizable (e.g. all for some children to not be cloned at all, by skipping their Include).
I'm looking for a way to get all records where deleted is set to true on a particular table. How might I accomplish this?
Note: Using auto-generated class by SubSonic. Not T-SQL.
The auto-generated SubSonic classes don't support querying logical deletes. But you can do this (version 2.1/2.2 syntax):
public partial class TableClassCollection
{
public TableClassCollection LoadAll(bool suppressLogicalDeletes)
{
SubSonic.SqlQuery q = new SubSonic.Select(TableClass.Schema)
.From(TableClass.Schema);
if (suppressLogicalDeletes)
{
q.Where(TableClass.DeletedColumn).IsEqualTo(false);
}
return q.ExecuteAsCollection<TableClassCollection>();
}
}
More examples at subsonicproject.com
I've never heard of SubSonic before, but a quick Google search turned up: Select Queries in SubSonic.
So, using that page as a guide, it sounds like you'd be able to write your query as:
FooCollection deletedFoos = // use the generated collection class
DB.Select().From("FooTable") // table name goes here
.Where("deleted").IsEqualTo(true) // might need 1, depends on database?
.ExecuteAsCollection<FooCollection>(); // should match the type above
not a lot of detail in your question, but assuming there's a column named "deleted," it would look something like this:
select * from tableName where deleted = true