My database structure has several MANY_MANY links. However Gii (giix in my case) does not always generate them as MANY_MANY, instead it generates a HAS_MANY with the joint table.
Are there rules to make sure Gii does the correct relationship? Does it look at the name of the columns? Names of the tables? Indexes? Foreign key names? What if there are other columns in the joint table?
Gii actually checks every table to see if there are join tables (see ModelCode::isRelationTable() in gii/generators/model). It detects a table as a join table if:
The table has 2 columns
Both columns are foreign keys
The foreign keys point to different tables
Gii then creates a many-to-many relationship between the participating models.
Gii creates many One to Many (1:n) relations self::BELONGS_TO + self::HAS_MANY in models
self::MANY_MANY need type manually
Related
I have a design problem with regards to Entity Framework model relationship
I have this model in the edmx
Business Rule:
A Participant can have multiple Roles so I create a relationship table ParticipantRoles that has 1-to-Many relationship on the Participant and the Role table
The Problem:
In order to get the Participant's Role value, I have to drill down through Participant->ParticipantRole->Role (see JSON output below)
The Question:
In EF, how to design the table relationship to bypass the ParticipantsRole table. I want to access the Role in something like this Particant.Role and not Participant.ParticipantsRole.Role
You say A Participant can have multiple Roles. And of course, a Role can have multiple Participants. So basically this is a many-to-many association.
Entity Framework will only map pure many-to-many associations (without connecting class) when the junction table only has two foreign keys. In your case, if the table ParticipantsRole only would have had a primary key consisting of ParticipantId and RoleId at the time of generating the model the class ParticipantsRole would not have been created. You would have had Participant.Roles and Role.Participants as navigation properties.
However, the model has been generated with ParticipantsRole and you want to get rid of it. (Or not, I'll get back to that).
This is what you can do:
Remove ParticipantRoles from the class diagram.
Modify the database table ParticipantRoles so it only has the two FK columns, that both form the primary key.
Update the model from the database and select ParticipantsRole in the Add tab.
This should give you a model with a pure many-to-many association.
However, think twice before you do this. M2m associations have a way of evolving into 1-m-1association (as you've got now). The reason is that sooner or later the need is felt to record data about the association, so the junction table must have more fields and stops being a pure junction table. In your case I can imagine that one day participant's roles must have a fixed order, or one marked as default. It can be a major overhaul to change a m2m association into 1-m-1 in a production environment. - Something to consider...
When I am translating an ER to SQL DDL I need to Create a table only for the entities or for the relations too?
Yes, you need to create tables for both entities and relationships. Also, keep in mind that you have to include foreign keys and link your tables
It depends what type of relationship you have. If it is many to many relationship then it must require a separate table for the relationship itself. Any way you can search on google ER diagram to relational database or look the text book on the relational model chapter of Modern database management sytem of author Hoffer.
You require a CREATE TABLE statement for each ENTITY.
Your relations ships are generally implemented as FOREIGN KEY CONSTRAINTS or FOREIGN KEY INDEXES between those tables.
Each entity becomes a table and each many to many relationship becomes a table.
Add the child columns (FK column) to the (child) tables also. When you create a N:M (many to many) relationship in for example DeZign for Databases, you see that an intersection table is create automatically. The columns which are added automatically are in first instance the columns of the primary key of both tables. You can see that in this video:
http://www.datanamic.com/support/vd-dez001.html
I'm new to Yii here. In the documentation, it seems to imply that gii will create the relations for related models. But when using gii to generate models from DB, it doesn't seem to be the case. For example, I have a user table and a profile table with a column "user_id INTEGER DEFAULT 0", but the relations array is empty in the generated model. Did I do something wrong, or gii just doesn't automatically recognize the relations?
Thanks,
Gii will create relations for MyISAM tables if you include a format like the following in the comment of the referenced columns:
CONSTRAINT FOREIGN KEY (name_of_this_field) REFERENCES related_table_name(related_field_name)
Gii can automatically create relations for generated models if corresponding tables in your DB have foreign keys, but not all storage engines support foreign keys. For example, if you use MyISAM tables in MySQL, you have no way to define it.
Say I have two tables
Products table:
|ProductID|ProductName|ListPrice|
PrebuiltSystems table:
|BuldID|Processor|Motherboard|RAM|
The values for the Processor, Motherboard etc. are all existing ProductID's. I am now creating
foreign key relationships from each of the part name columns to the one ProductID and have a bunch of navigation properties and relationships lines being created for each part. Is this ok?
Or is there some kind of relationship merger/rule that I can use to say all those columns are foreign keys to productID without creating one to one relationships ?
Is this ok?
Yes, this is the right way to do it.
Or is there somekind of relationship merger/rule that I can use to say
all those columns are foreign keys to productID
No, they are all different relationships.
without creating one to one relationships ?
Note that these are many-to-one, not one-to-one relationships, many PrebuiltSystems will have the same Processor
Yes it is fine to have multiple foreign keys. However, in your example, I'd still do it differently; if you have one column for each component type you limit yourself very much. What do you do with a multi-CPU-system? What with multiple harddisks etc.?
You should rather normalize the PrebuiltSystems table so that you have a link table which creates a n-to-n relationship to the products (e.g. each product can be part of any number of prebuilt systems, and each prebuilt system can have any number of products in it).
(VS2008, SqlCE 3.5)
I try to model a 1:1 relationship. So I put the foreign key in the parent table, holding the PK of the child table. Then I set the foreign key to UNIQUE. Still when I create my entity classes (With SqlMetal), the child class has a reference to an EntitySet of the parent, not just a single entity. This seems like a m:1 relation? So what I need to do to make it 1:1 ?
EDIT1:
I'm confused.. Trying to make a set, like this:
StrategySet(ID, EntryStrategyID{Unique}, ExitStrategyID{Unique})
EntryStrategy(ID)
ExitStrategy(ID)
Is this m:1 isn't it? Though it looks like FK's are in the parent, or wouldn't we name StrategySet the parent? And how would I now change this too 1:1 ?
First of all, the parent is table which is referenced by FK from child. So you can't say that your parent table references the child: it's not correct.
Secondly, 1:1 relations can be made through:
Primary Keys in both tables
Primary Key in parent and Unique Foreign Key in child
So in your case, the architecture is correct. I suppose you should check the structure again, and look through this article.
If all columns in EntryStrategy and ExitStrategy are the same, then all you need is simply this (add all other columns too).
If EntryStrategy and ExitStrategy have some different columns, then use this. Keep all common columns in the Strategy table. EntryStrategy and ExitStrategy have only columns specific to each one.
Here is also a generic example of 1:1 due to vertical partitioning of a table.
Before:
After:
Let me understand the situation you are describing.
You have set of fields which make up a "Strategy". A subset of the fields are conceptually the "EntryStrategy" and a non-intersecting subset of the fields are the "ExitStrategy".
In your case a given set of values making up an "EntryStrategy" can be joined with one and only one set of values making up an "ExitStrategy". This is what you mean when you say there is a 1:1 correspondence.
As smirkingman said earlier, in classic relational database modeling, all of these fields belong in a single table because no subset of the fields appear in more than one record.
If you could have multiple ExitStrategies for a single EntryStrategy then you would have two tables with the EntryStrategy being the parent and the ExitStrategies being the children and the ExitStrategy records would have a Foreign Key pointing to the EntryStrategy parent record.
If you could have multiple EntryStrategies for a single ExitStrategy then you would have two tables with the ExitStrategy being the parent and the EntryStrategies being the children and the EntryStrategy records would have a Foreign Key pointing to the ExitStrategy parent record.
If you could have multiple EntryStrategies associated with multiple ExitStrategies then you would have a many-to-many relationship which requires a third table to maintain the correspondences.
The principles of classic database modeling would put all your fields in one table.
As St Woland wrote, you can enforce the 1:1 relationship by having two tables where the foreign key in the child table is a Unique index. But two tables are normally used for 1-to-many relationships.
As Damir wrote, you can enforce the 1:1 relationship by having three tables where the third table has a foreign key to each of the other two tables and both foreign key fields are marked as Unique indices. However, normally you only use three tables in this fashion when you have a many-to-many relationship.
I think you are expecting way too much from the automated data modeling tools to expect them to construct entities that represent your very unconventional approach.
The answer to your main question is simple. How do I represent a 1:1 relationship? You put them in the same record in a single table!