I have an entity that I have deserialized using JMSSerializer. One of the related items is an ArrayCollection that has no entries in it when the parent object is initially created.
The relationship looks like this
Assembly > has many > HistoryEntries
When I try to merge the deserialized Assembly entity where HistoryEntries is an empty ArrayCollection I get the following error
The given entity of type 'XES\\MpmBundle\\Entity\\History' (unassigned) has no identity/no id values set. It cannot be added to the identity map.
How can I merge and persist an entity where one or more of the relationships has no related entities?
Related
Are entity id's idempotent when saving multiple entities with the same id?
I want to ensure only one entity of a specific id exists in my Datastore. I was thinking that I could give it a String id that I create (based off of other data) and if in the future the same entity gets saved again with the same id, the entity will just get overwritten (but two entities will not ever exists).
Am I correct in my thinking or does it not work that way?
An entity key uniquely identifies an Entity. So saving an entity with the same key, but different values is not idempotent, but results in only a single entity. The key for an entity can be thought of as a list of (Kind, name or id) tuples. name would be a string, and id an integer.
In Objectify, if you use #Id with a string, then you'd access that part of the key with getName()
We inherited a 3rd party database schema where several tables use a database
design pattern in which tables do not define foreign keys directly, but in
a way where some tables do so by a combination of two columns:
a column specifying name of table:
either directly (ENUM type)
or by means of another table (type_id referencing table types, which then contains table name in a varchar column)
a column specifying PK value from said table (e.g. type_value)
This results in a scenario where one row references one table while another
row may reference a completely different table.
We can use query builder and define JOIN and WHERE clauses manually for each
scenario, but it'd be more practical to have one property for each foreign
table and use WHERE clause to filter target table results only, e.g.:
class Foo {
private $id; // PK for Foo
private $type; // string (enum), e.g. 'bar' or 'baz'
private $type_id; // contains PK of Bar or Baz, respectivelly
private $bar; // references entity Bar
private $baz; // references entity Baz
}
The closest thing to what we need which I managed to find is to use Criteria API
to update the WHERE clause dynamically in getter methods (as seen here).
However I'm completely lost in terms of how to setup Doctrine annotations in
this case. Does Doctrine support a DB schema such as this one, or do we have to
fall back to building each query manually via query builder or DQL?
I want to add the option onDelete="CASCADE" on one of my attributes via the #JoinColumn annotation:
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Product",mappedBy="category",fetch="EAGER")
* #ORM\JoinColumn(onDelete="CASCADE")
*/
private $products;
But when I try to update with php bin/console doctrine:schema:update --force , I always get:
nothing to uptade - database already sync.
I tried to add some other attributes and I got the same issue. However, if I intentionally add a mistake I get an error as expected.
How can I fix this?
The #OneToMany annotation is the one you use on the inverse side of your many-to-one association. The table storing the entities on this side of the association does not hold any foreign key pointing to the table storing your Product entities, thus there is no "join column" there.
The documentation states the following about #JoinColumn:
This annotation is used in the context of relations in #ManyToOne, #OneToOne fields and in the Context of #JoinTable nested inside a #ManyToMany.
In your case, the annotation does not apply to any column at all and consequently, your database does not need to be updated.
If you wish to have Product entities related to a given Category removed through cascade operations by your database, you have to add a #JoinColumn(onDelete="CASCADE") on the owning side of the association, next to the #ManyToOne annotation of the category attribute of Product.
I have a foreign key relationship between two tables UserProducts and Users in my database, with UserProducts having a UserID referencing the UserID in the Users table.
ALTER TABLE [dbo].[UserProducts] WITH CHECK ADD CONSTRAINT [FK_UserProducts_Users] FOREIGN KEY ([UserID])
REFERENCES [dbo].[Users] ([UserID])
GO
ALTER TABLE [dbo].[UserProducts] CHECK CONSTRAINT [FK_UserProducts_Users]
GO
The UserID column in the UserProducts table is part of a composite primary key with another column ProductID. There are also two additional DateTime columns, so Entity Framework does not treat UserProducts as a link table.
There is NO cascade delete on that foreign key above, nor did I set up anything to handle OnDelete on the Entity Framework foreign key association. Yet, when I delete a User entity from code, Entity Framework is taking the liberty of deleting the UserProducts associated with it by UserID. It is also generating a lot of SQL to do it: there is a separate DELETE per related record in the UserProducts table.
The code to perform the entity deletion is as follows:
using (var context = new LicensingRegistrationContext(_csb))
{
context.Database.Log = a => _logger.Trace(a);
var dbUser = GetUserDbSetWithIncludes(context)
.Where(a => a.UserID == user.Id).Single();
context.DbUsers.Remove(dbUser);
//TODO(MRL): Um...how are the dbUserProducts being removed???
context.SaveChanges();
}
How is this happening? In EF 4 I am pretty sure EF never took this liberty of doing this: you HAD to load and then delete all related entities manually in code.
Thanks
Entity framework by default has a
OneToManyCascadeDelete
convention. Here is the link http://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.conventions.onetomanycascadedeleteconvention(v=vs.113).aspx
So entity framework cascade deletes the one to many relationship by default.
You can disable this by disabling the convention or explicitly disabled it for this relationship via the fluent API.
I found this on MSDN and I believe this is what is happening:
When a primary key of the principal entity is also part of the primary key of the dependent entity, the relationship is an identifying relationship. In an identifying relationship the dependent entity cannot exist without the principal entity. This constraint causes the following behaviors in an identifying relationship: Deleting the principal object also deletes the dependent object. This is the same behavior as specifying OnDelete Action="Cascade" in the model for the relationship. Removing the relationship deletes the dependent object. Calling the Remove method on the EntityCollection marks both the relationship and the dependent object for deletion.
This is what is happening in my model where the UserComponent table has a composite primary key: UserID, ComponentID and the UserID column is a foreign key to the UserID in the User table.
I have a table "Category" and another "Subcategory". Then I have "Products" table.
Some of these products will be related directly to the "Subcategroy" table, but some of them will be related directly to "Category". What should be the tables structure in this case?
Use Association Mapping
This chapter explains mapping associations between objects.
Instead of working with foreign keys in your code, you will always work with references to objects instead and Doctrine will convert those references to foreign keys internally.
http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html