Here's my table structure:
Person
PersonID int
Address
AddressId int
Address varchar
PersonAddress
PersonID int primary key references Person.PersonID
AddressID int primary key references Address.AddressID
As you can see there is no relation between Person and Address. When I add these 3 tables to EF 6.0, it does not add the PersonAddress table but adds a relationship between Person and Address. I am deeply confused.
EF is doing exactly what you want. In EF you have a relationship between OBJECTS, not SCHEMA. The object relationship between Person and Address can be accomplished without the need of a third object. This reduces the complexity and makes the code easier to manage. EF will handle translating the relationship back and forth to the schema as needed.
Related
I have a quick question with respect to many to many relationships in sql.
So theoretically i understand that if 2 entities in an ER model have a M:N relationship between them, we have to split that into 2 1:N relationships with the inclusion of an intersection/lookup table which has a composite primary key from both the parent tables. But, my question here is , in addition to the composite primary key, can there be any other extra column added to the composite table which are not in any of the 2 parent tables ? (apart from intersectionTableId, table1ID, table2ID) a 4rth column which is entirely new and not in any of the 2 parent tables ? Please let me know.
In a word - yes. It's a common practice to denote properties of the relationship between the two entities.
E.g., consider you have a database storing the details of people and the sports teams they like:
CREATE TABLE person (
id INT PRIMARY KEY,
first_name VARCHAR(10),
last_name VARCHAR(10)
);
CREATE TABLE team (
id INT PRIMARY KEY,
name VARCHAR(10)
);
A person may like more than one team, which is your classic M:N relationship table. But, you could also add some details to this entity, such as when did a person start liking a team:
CREATE TABLE fandom (
person_id INT NOT NULL REFERENCES person(id),
team_id INT NOT NULL REFERENCES team(id),
fandom_started DATE,
PRIMARY KEY (person_id, team_id)
);
Yes, you can do that by modeling the "relationship" table yourself explicitly (just like your other entities).
Here are some posts about exactly that question.
Create code first, many to many, with additional fields in association table
Entity Framework CodeFirst many to many relationship with additional information
I have implemented the following ways of storing relational topology:
1.A general junction relation table:
Table: Relation
Columns: id parent_type parent_id parent_prop child_type child_id child_prop
On which joins are not generally capable of being executed against by most sql engines.
2.Relation specific junction tables
Table: Class2Student
Columns: id parent_id parent_prop child_id child_prop
On which joins are capable of being executed against.
3.Storing lists/string maps of related objects in a text field on both bidirectional objects.
Class: Class
Class properties: id name students
Table columns: id name students_keys
Rows: 1 "history" [{type:Basic_student,id:1},{type:Advanced_student,id:3}]
To enable joins by the sql engines, it would be possible to write a custom module which would be made even easier if the contents of students_keys was simply [1,3], ie that a relation was to the explicit Student type.
The questions are the following in the context of:
I fail to see what the point of a junction table is. For example, I fail to see that any problems the following arguments for a junction table claim to relieve, actually exist:
Inability to logically correctly save a bidirectional relations (eg
there is no data orphaning in bidirectional relations or any
relations with a keys field, because one recursively saves and one can enforce
other operations (delete,update) quite easily)
Inability to join effectively
I am not soliciting opinions on your personal opinions on best practices or any cult-like statements on normalization.
The explicit question(s) are the following:
What are the instances where one would want to query a junction table that is not provided by querying a owning object's keys field?
What are logical implementation problems in the context of computation provided by the sql engine where the junction table is preferable?
The only implementation difference with regards to a junction table vs a keys fields is the following:
When searching for a query of the following nature you would need to match against the keys field with either a custom indexing implementation or some other reasonable implementation:
class_dao.search({students:advanced_student_3,name:"history"});
search for Classes that have a particular student and name "history"
As opposed to searching the indexed columns of the junction table and then selecting the approriate Classes.
I have been unable to identify answers why a junction table is logically preferable for quite literally any reason. I am not claiming this is the case or do I have a religious preference one way or another as evidenced by the fact that I implemented multiple ways of achieving this. My problem is I do not know what they are.
The way I see it, you have have several entities
CREATE TABLE StudentType
(
Id Int PRIMARY KEY,
Name NVarChar(50)
);
INSERT StudentType VALUES
(
(1, 'Basic'),
(2, 'Advanced'),
(3, 'SomeOtherCategory')
);
CREATE TABLE Student
(
Id Int PRIMARY KEY,
Name NVarChar(200),
OtherAttributeCommonToAllStudents Int,
Type Int,
CONSTRAINT FK_Student_StudentType
FOREIGN KEY (Type) REFERENCES StudentType(Id)
)
CREATE TABLE StudentAdvanced
(
Id Int PRIMARY KEY,
AdvancedOnlyAttribute Int,
CONSTRIANT FK_StudentAdvanced_Student
FOREIGN KEY (Id) REFERENCES Student(Id)
)
CREATE TABLE StudentSomeOtherCategory
(
Id Int PRIMARY KEY,
SomeOtherCategoryOnlyAttribute Int,
CONSTRIANT FK_StudentSomeOtherCategory_Student
FOREIGN KEY (Id) REFERENCES Student(Id)
)
Any attributes that are common to all students have columns on the Student table.
Types of student that have extra attributes are added to the StudentType table.
Each extra student type gets a Student<TypeName> table to store its specific attributes. These tables have an optional one-to-one relationship with Student.
I think that your "straw-man" junction table is a partial implementation of an EAV anti-pattern, the only time this is sensible, is when you can't know what attributes you need to model, i.e. your data will be entirely unstructured. When this is a real requirment, relational databases start to look less desirable. On those occasions consider a NOSQL/Document database alternative.
A junction table would be useful in the following scenario.
Say we add a Class entity to the model.
CREATE TABLE Class
(
Id Int PRIMARY KEY,
...
)
Its concievable that we would like to store the many-to-many realtionship between students and classes.
CREATE TABLE Registration
(
Id Int PRIMARY KEY,
StudentId Int,
ClassId Int,
CONSTRAINT FK_Registration_Student
FOREIGN KEY (StudentId) REFERENCES Student(Id),
CONSTRAINT FK_Registration_Class
FOREIGN KEY (ClassId) REFERENCES Class(Id)
)
This entity would be the right place to store attributes that relate specifically to a student's registration to a class, perhaps a completion flag for instance. Other data would naturally relate to this junction, pehaps a class specific attendance record or a grade history.
If you don't relate Class and Student in this way, how would you select both, all the students in a class, and all the classes a student reads. Performance wise, this is easily optimised by indices on key columns.
When a many-to-many realtionships exists without any attributes I agree that logically, the junction table needn't exist. However, in a relational database, junction tables are still a useful physical implmentaion, perhaps like this,
CREATE TABLE StudentClass
(
StudentId Int,
ClassId Int,
CONSTRAINT PK_StudentClass PRIMARY KEY (ClassId, StudentId),
CONSTRAINT FK_Registration_Student
FOREIGN KEY (StudentId) REFERENCES Student(Id),
CONSTRAINT FK_Registration_Class
FOREIGN KEY (ClassId) REFERENCES Class(Id)
)
this allows simple queries like
// students in a class?
SELECT StudentId
FROM StudentClass
WHERE ClassId = #classId
// classes read by a student?
SELECT ClassId
FROM StudentClass
WHERE StudentId = #studentId
additionaly, this enables a simple way to manage the relationship, partially or completely from either aspect, that will be familar to relational database developers and sargeable by query optimisers.
Conceptual stage question:
I have several Tables (Person, Institution, Factory) each has many kinds of Addresses (Mailing, Physical)
Is there a way to create a single Address table that contains all the addresses of all the Entities?
I'd rather not have a PersonAddress and FactoryAddress etc set of tables.
Is there another option?
The amount of data will only be several thousand addresses at most, so light in impact.
My proposal relies on the principle that one entity (person, Institution, Factory, etc) can have multiple adresses, which is usually the case (home, business, etc), and that one adress can be shared by entities of different nature:
CREATE TABLE ADDRESS
(
ID INT IDENTITY PRIMARY KEY NOT NULL,
.... (your adress fields here)
id_Person ... NULL,
id_Institution ... NULL,
id_Factory ... NULL
)
The main limit is that 2 different persons cannot share the same adress. In such a situation, you'll have to go with an additional "EntityAddress" table, like this:
CREATE TABLE ADDRESS
(
ID INT IDENTITY PRIMARY KEY NOT NULL,
.... (your adress fields here)
)
CREATE TABLE ENTITY_ADDRESS
(
ID INT IDENTITY PRIMARY KEY NOT NULL
id_Address .... NOT NULL,
id_Person .... NULL,
id_Institution ... NULL,
id_Factory .... NULL
)
The last model allows you to share for example one adress for multiple persons working in the same institution.
BUT: according to me, the 'better' solution would be to merge your different entities into one table. You will then need:
An Entity Table, made for all entities
An Entity Type table, that will contain the different entity types.
In your case you have at least 3 rows: persons, factories,
institution
If one adress per entity is enough, you could go for the address details as properties of the Entity table.
If you need multiple addresses by entity, you'll have to go with the Addresses Table with an Id_Entity as a foreign key.
If you want to share one adress among multiple entities, each entity having potentially multiple adresses (a many-to-many relation between entities and adresses), then you will need to go for the EntityAddres table in addition to the Entity and Address Tables.
Your choice between these models will depend on your needs and your businness rules.
You need to use abstraction and inheritance.
An individual and institution (I'd call it organization) are really just concrete representations of an abstract legal party.
A mailing or physical address is the concretion of an abstract address, which could also be an email address, telephone number, or web address.
A legal party can be have zero or more addresses.
An address can be belong to zero or more legal parties.
A party could use the same address for multiple roles, such as 'Home' address and 'Work' address.
If a factory is big enough, sub-facilities in the factory might have their own addresses, so you might want to consider a hierarchical relationship there. For example, each apartment in a condo has one address each. Each building in a large factory might have their own address.
create table party (
party_id identity primary key
);
create table individual (
individual_id int primary key references party(party_id),
...
);
create table organization (
organization_id int primary key references party(party_id),
...
);
create table address (
address_id identity primary key,
...
);
create table mailing_address (
address_id int primary key references address(address_id),
...
);
create table party_address (
party_id int references party(party_id),
address_id int references address(address_id),
role varchar(255), --this should really point to a role table
primary key (party_id, address_id, role)
);
create table facility (
facility_id identity primary key,
address_id int not null references address(address_id),
parent_id int null references facility(facility_id)
);
in my opinion ,you should create a pivot table to link Entity with her Address
for exampleinstitution_addresses(id, id_institution,id_address), person_addresses(id,id_person,id_address) etc...
You could very definitely do this. You could have the Address table that has an ID, then Person, Institution and Factory could all have foreign keys to the Address table.
If you need to be able to distinguish what kind of Address it is at the Address level, you could consider adding an AddressType table and having a foreign key to that on the Address table
Example:
CREATE TABLE ADDRESS
(
ID INT IDENTITY PRIMARY KEY NOT NULL,
City VARCHAR(50) NOT NULL,
State VARCHAR(2) NOT NULL,
Zip VARCHAR(10) NOT NULL,
AddressLine1 VARCHAR(200) NOT NULL,
AddressLine2 VARCHAR(200) NOT NULL,
)
CREATE TABLE Person
(
ID INT IDENTITY PRIMARY KEY NOT NULL,
AddressID INT FOREIGN KEY REFERENCES Address(ID)
)
CREATE TABLE Institution
(
ID INT IDENTITY PRIMARY KEY NOT NULL,
AddressID INT FOREIGN KEY REFERENCES Address(ID)
)
...etc
Another basic \ bullet proof system would be to organise your model around:
An Entity Table, made for all entities
An Entity Type table, that will contain the different entity types. In your case you have at least 3 rows: persons, factories, institution
If one adress per entity is enough, you could go for the address details as properties of the Entity table.
If you need multiple addresses by entity, you'll have to go with the Addresses Table with an Id_Entity as a foreign key.
If you want to share one adress among multiple entities, each entity having potentially multiple adresses (a many-to-many relation between entities and adresses), then you will need to go for the EntityAddres table in addition to the Entity and Address Tables.
EDIT: this answer was also merged with the other answer I gave here ... so I do not know if it deserves an upvote!
I'm trying to create 2 tables in Visual Studio server pane and I have a problem creating the foreign keys.
When I'm trying to create them in the relationship page it won't let me create foreign keys until I make them primary keys.
I don't understand why I can't have a different member in my table that it is primary key and a different one a foreign key.
My tables are like this:
Table People:
Primary key: ID int
Name nvarchar
Age int
City nvarchar
Foreign key: AccountNumber int --> when I make him primary key everything works.
Table BankAccount:
Primary key and Foreign Key: AccountNumber int
Money float
ps.
I used some mysql with CMD and I remember that I could do this, but because I don't have this control in visual studio I'm lost.
UPDATE:
Rup made a good point that i only relize afther answering the qustion he ask me
i just did the realtionship (Foreign Key) for the bank account table and now i got
what i wanted thank you!
Why is BankAccount.AccountNumber a Foreign Key? Are you trying to reference back to the the person who owns it?
If that is the case, BankAccount should be:
CREATE TABLE BankAccount
(
AccountNumber int PK,
Money float, // bad idea. Use currency or int (i.e. store balance as pennies)
Owner int FK REFERENCES People.ID
)
And drop the account ID from the people table.
This models the relationship "an Account has 1 and only one owner" and allows the relationship "A person can have many accounts."
It looks like what you're trying to do is create a back reference. If you were to choose to do this, then the back reference to the owner should be on People.ID, not on account. -- Although this is unnecessary because you can simply query
SELECT * FROM
BankAccount INNER JOIN People ON BankAccount.Owner = People.ID
to get all accounts and their owners.
If you want to establish multiple owners for an account, AND many accounts per user, then you need to establish a third table to implement the many-to-many relationship.
CREATE TABLE AccountOwners
(
AccOwnID int PK,
AccountID int FK REFERENCES BankAccount.AccountNumber,
PeopleID int FK REFERENCES People.ID
)
And drop the People.AccountNumber and BankAccount.Owner. This technique is akin to maintaining a list of all accounts and owners which you can query.
I have a problem with one-to-one relationships in the fluent nHibernate.
I have the following relational table from the AdventureWorks2008 database.
BusinessEntity (Table)
BusinessEntityId Int (PK, Identity)
Person (Table)
BusinessEntityId int (PK, Reference with BusinessEntity table)
FullName varchar(255)
The relationship between BusinessEntity table and Person table is one-to-one.
How do I map fluently without any extra field like "Id" in the Person table?
There should be 2 class one for Person and another for BusinessEntity, or an appropriate model to best describe the above relation.
Thanks,
Ashraf.
presuming your Person mapping is pretty standard, the way you do this is by saying:
Id(x => x.BusinessEntityId)
.GeneratedBy.Foreign("BusinessEntity");
on the Person class.
This presumes that your Person class has a property called BusinessEntity which is of type BusinessEntity.
You'll also need to map BusinessEntity to Person with constrained set to true (to say that they primary key of Person is a foreign key reference to BusinessEntity).
The key thing is the GeneratedBy.Foreign() to say that your identity is generated by a link to another class.