Is it possible to establish an association in Doctrine2 without target entity at hand? - orm

There is a ManyToOne association defined between entities Pattern and Category (Pattern is an owning side of the relation). Category has many patterns, pattern belongs to one category. So there is a field Pattern.category with #ManyToOne Doctrine annotation.
Now, in my scenario I have the id of the Category entity (posted from form) that I want assign to Pattern.category field of the newly created Pattern (which will be persisted), but I don't want to load this Category entity - I don't need it, I just want to create a Pattern entity, assign it to a Category (which id I have), and persist it. It seems strange to me, that I have to load the Category entity just to establish the connection, when all I really need is just an id, which I already have.
Maybe it smells like using relational database concepts with ORM, but it seems completely pointless to load this entity just to establish connection, when I know id of that target entity.
I am new to Doctrine btw.

You can use Reference Proxy:
$category = $em->getReference('Category', $id);
$pattern->setCategory($category);

Related

A non-standard many-to-many relationship in NHibernate

I have two tables (Rule and Object) linked through a many-to-many relationship. A Rule may be associated with any number of Objects, or it may be associated with all Objects.
I would normally build this association with a link table where, the Object_ID column would be set to NULL if the associated Rule was to be associated with all Objects. Any value that won't actually reference a real Object will do.
This way, I could write an Select to find all Rules associated with an object like this:
SELECT * FROM Rule JOIN RuleObject_Link on Rule.ID = RuleObject_Link.RuleID WHERE RuleObject_Link.ObjectID = <the object ID> or RuleObject_Link.ObjectID IS NULL
The problem is that I am using NHibernate. I can't find a way to signify "all Objects" in the automated relationship/collection structure.
Is it possible to build a relationship like this using NHibernate's many-to-many relationship?
Or will I have to manually configure the link table and handle the connection myself?
It would be better to add a separate boolean field to Rule signifying that it applies universally to all Object objects (Object is a pretty bad classname by the way).
This really doesn't participate in the relationship mapping, and getting the entire list of rules for an object would require a query rather than being populated automatically from mappings, but I can't think of anything better right now.

Doctrine ORM Single Table Inheritance association problem (always Eager loading contrary to documentation))

I have an issue with single table inheritance and I'm not sure if I'm interpreting the documentation correctly.
First: I've not copied my code / entity mappings verbosely (or even using the correct syntax) here as I think the problem can be better communicated abstractly.
If this is not acceptable by all means say so and I'll add the full code - but it is LONG and I think my question can be answered without it.
If it helps I can draw
an ER diagram to try and communicate what I'm trying to do.
If you read the following and think 'hey that should work' - then tell me and I'll upload the real code
Second: I don't use lazy loading anywhere. Before accessing my entities I make sure that I load every related entity that I'm going to be accessing by writing DQL up front - so the following issue is fairly terminal to my application)
The Setup:
I have some entities - these make up the core of my application.
// #entity AnimalTrainingSchool
// oneToMany: trainingDepartment
fields: [name / location / year founded]
// #entity trainingDepartment
oneToMany: animalTrainer
oneToOne: building
fields: [capacity]
// #entity animalTrainer
fields: [name / age / qualification]
I access them frequently and in different contexts - but I commonly iterate though levels and access properties and relations for these entities.
foreach ($animalTrainingSchool as $school){
echo $school->getName() . ' at ' . $school->getLocation();
echo 'These are the training departments for this school:';
foreach ($school->getTrainingDepartments as $trainingDepartment){
echo $trainingDepartment->getAnimalTypeTrained() . ' are trained in this department';
}
}
I make sure that all of these are loaded up front by forming my DQL and executing it - to limit the number of SQL queries (to one).
This all works great (fairly standard stuff).
DQL Example : "SELECT ats, td, at FROM AnimalTrainingSchool ats JOIN AnimalTrainingSchool.trainingDepartments td JOIN td.animalTrainer at";
This sets up my collection and means that I can traverse it without having to issue additional queries
The Problem:
I have mapped other entites elsewhere in my application - very similarly to this (NOTE: My overall question is very similar to the below question with one MAJOR difference (see below)
Doctrine 2 Inheritance Mapping with Association
// NB: new awards are issued each time they are awarded - so it is meant to be a oneToOne relationships - the awards are unique
// #entity award
{id information / table information / discriminator map / inheritance type (SINGLE_TABLE)}
fields: [medalMaterial / award_serial_number]
//departmentAward extends award
oneToOne: trainingDepartment
//trainerAward extends award
oneToOne: animalTrainer
then I made the relationship bidirectional by modifying my initial entities
// #entity trainingDepartment
oneToMany: animalTrainer
oneToOne: building
oneToOne: departmentAward
fields: [capacity]
// #entity animalTrainer
fields: [name / age / qualification]
oneToOne: trainerAward
What Happens
Now when I access my original entities in exactly the same way as above - they automatically (eagerly) load the associated entity for their awards though I'm not telling them to.
This is especially bad when I'm iterating though a whole bunch of trainingDepartments / AnimalTrainers and Doctrine is executing an SQL statement for EVERY entity.
For 20 departments with 10 trainers in each - this is 200 additional queries.
//Given the exact same DQL and foreach loop as above (note that at no stage am I accessing awards) - I get a ton of extra queries that look like this
"SELECT award.property1, award.property2, award.property3 FROM awardTable LEFT JOIN trainingDepartmentTable ON award.awardee_id = trainingDepartmentTable.id and award.discriminatorColumn IN ('departmentAward')";
// or...
"SELECT award.property1, award.property2, award.property3 FROM awardTable LEFT JOIN animalTrainerTable ON award.awardee_id = animalTrainerTable.id and award.discriminatorColumn IN ('trainerAward')";
None of what is being generated is incorrect - it's just that having read the following question it seems to me like I have set this up as the documentation describes (and in the opposite way to #Matthieu; namely - that If I related my initial 3 entites to the LOWEST level entities
rather than the 'award' base class then they SHOULD be able to use proxies instead of attempting to eagerly load the entities.
Stackoverflow Question which is asking the opposite of what I am describing
Doctrine 2 Inheritance Mapping with Association
Relevant Doctrine Documentation
http://www.doctrine-project.org/docs/orm/2.0/en/reference/inheritance-mapping.html#performance-impact
There is a general performance
consideration with Single Table
Inheritance: If you use a STI entity
as a many-to-one or one-to-one entity
you should never use one of the
classes at the upper levels of the
inheritance hierachy as
“targetEntity”, only those that have
no subclasses. Otherwise Doctrine
CANNOT create proxy instances of this
entity and will ALWAYS load the entity
eagerly.
It seems to me that regardless of whether or not you are joining to the base level entity or a subclassed entity - Doctrine will eagerly load the associations and will not attempt to use proxies.
Again: I can post real code - but given the length of the question already I felt it was best not to. Any input greatly appreciated.
The inverse side of a oneToOne relationship can not be lazy loaded. In order to support lazy loading, Doctrine needs to create a proxy object, but proxy objects need to have an identifier associated with them. In the case of oneToOne relationships, the identifier is only available on the owning side. So the inverse relationship has to be loaded eagerly.
You should try to fetch join these associations if possible. Version 2.1 will automatically force fetch joins for inverse oneToOne relationships.

Specifying the Table on a HasMany() relationship mapping in FluentNHibernate

I have a mapping in FluentNHibernate for a HasMany relationship and I'd like to specify a Table on it to override the default Table that nHibernate will look in to find those objects that I have many of. Does that make sense?
So lets say I have a table for Invoices and a table for InvoiceItems and lets say I have table called InvoiceItemsTwo.
I have a class for Invoice and a Class for InvoiceItems as well, and their mappings are pretty straight forward. I'd like to specify in my mapping for Invoice, that it should look for it's items in InvoiceItemsTwo instead of the default InvoiceItems.
So my mapping of that relationship looks like this
HasMany(c => c.InvoiceItems).Cascade.SaveUpdate().Table("InvoiceItemsTwo");
But this doesn't work. I keep getting an error from my website at runtime that says Invalid object name 'InvoiceItems'.
Why is it ignoring the fact that I am explicitly specifying the Table in my mapping on the relationship?
I tried dumping the mapping at run time and it's being setup something like this
<bag cascade="save-update" table="InvoiceItemsTwo">
Any ideas?
The table attribute applies only to many-to-many relationships, not one-to-many.
you can't specify a different table in your mapping class. Fluent NHibernate uses the class mapped on the property list (InvoiceItems).
If yoy want to use another class to map your details table you must create a InvoceItemsTwo class and map it in your master table class.
You could map the list as composite-element instead of a one-to-many relation and then map it to another table. But it is not a good idea. Consider that NH needs to know where to store an object which is in memory. So it may happen that the object is stored in the wrong table.
Either store all the InvoiceItems in separate tables using composite-element instead of one-to-many and components instead of many-to-one (however this is called in Fluent).
Or store all the InvoiceItems in the same table and use regular references.

Separate table for Value Objects on NHibernate

I'm new to DDD and NHibernate.
In my current project, I have an entity Person, that contains a value object, let's say Address. Today, this is fine. But maybe one day I will have a requirement that my value object (in this case Address), will have to become an entity.
Before trying to model this on a DDD-way, in a more data-centric approach, I had a table Person, with an Id, and another table Address, whose PK was actually an FK, it was the Id of a Person (ie, a one-to-one relationship).
I've been reading that when I map a Value Object as a Component, its value will get mapped as columns on my Entity table (so, I would not have the one-to-one relationship).
My idea was that, when needed, I would simply add a surrogate key to my Address table, and then it becomes an Entity.
How should I design this using NHibernate? Should I already make my Address object an Entity?
Sorry, I don't even know if my questions are clear, I'm really lost here.
In the system we are building, we put Value-Objects in separate tables. As far as I know, NHibernate requires that an id must added to the object, but we ignore this and treat the object as a Value-Object in the system. As you probably know, a Value-Object is an object that you don't need to track, so we simply overlook the id in the object. This makes us freer to model the database the way we want and model the domain model the way we want.
You can Join and make it a Component allowing nHibernate to map it as a proper value object instead of an entity.
This way you won't need any virtual properties nor an empty protected ctor (it can be private).
Join("PROPOSAL_PRODUCT", product =>
{
product.Schema(IsaSchema.PROPOSALOWN);
product.KeyColumn("PROPOSAL_ID");
product.Component(Reveal.Member<Proposal, Product>("_product"), proposalProduct =>
{
proposalProduct.Map...
});
});

Association end is not mapped in ADO entity framework

I am just starting out with ADO.net Entity Framework I have mapped two tables together and receive the following error:
Error 1 Error 11010: Association End 'OperatorAccess' is not mapped. E:\Visual Studio\projects\Brandi II\Brandi II\Hospitals.edmx 390 11 Brandi II
Not sure what it is I am doing wrong.
I believe I can add some more clarity to the issue (learning as I go):
When I look at the Mapping details and look at the association, the column for operatoraccess table (from above) is blank and the drop down only includes field from the linked table.
The Entity Framework designer is terrible - I've had the same problem many times (and your problem too, Craig):
This happens when you have a many-to-one association which is improperly setup. They could very easily fix the designer to make this process simple; but instead, we have to put up with this crap.
To fix:
Click on the association, and go to the mapping details view.
Under association, click on Maps to <tablename>. Choose the table(s) which make up the many side of the relationship (ie. the table(s) which make up the *-side of the association in the designer)
Under Column, choose the table-columns which map to each entity-side Property. You get this error when one of those entries are blank.
I had the exact same problem and this is what I did to fix it.
Make sure you have an Entity Key set in your designer on the tables your making an association with. Also check that StoreGeneratedPattern is set to Identity for that Entity Key.
There's not a lot of information in your question, but, generally speaking, this means that there is an incompletely defined association. It could be that you have tried to map one table with a foreign key to another table, but have not mapped that other table. You can also get this error when you try to do table per type inheritance without carefully following the steps for implementing that feature.
Not sure of the answer, but I've just posted a similar question, which may at least help clarify the issue you are experiencing.
Defining an Entity Framework 1:1 association
I had to go back into the database itself and clarify the foreign key relationship
I had this problem in the case where I was creating both many to 0..1 and 0..1 to 0..1 associations. One entity needed associations to multiple tables, and that entity did not have foreign keys defined for those tables.
I had to do the table mappings step that is given in the accepted answer, but note that it wasn't only for many to many associations; it applied to all the types of associations I added for this entity.
In the Mapping Details view, I had to select the entity with the non-foreign key ID columns to the various tables. This is not always the "many" side of the relationship. Only there was I able to map the related entity property to the appropriate property in the original entity. Selecting the "destination" entity would not allow me to select the properties that I needed to, and the error would still exist.
So in short, I had to map using the table related to the entity that had the "non-foreign key" ID fields corresponding to the various entities' (and their tables') primary keys that I needed to associate.
Entity A
various other properties...
Id
ContactId
OrderId
etc.
Contact entity
Id
FirstName
LastName
etc.
In the mapping details, I selected Entity A's table. It then showed both ends of the association. I mapped its Entity A's Id property to its table's actual ID column (they had different names). I then mapped the Contact entity's Id field to the ContactId field on the A entity.
Simply select the many relationship table (*) from the Association>Edit Mapping & select the appropriate relationship