How to use Entity Framework 6 to update many-to-many relationship? - entity-framework

Someone else asked a similar question here: How can I use EF6 to update a many to many table
I mention that up front because I couldn't get any of the solutions given to work.
I also studied the solution give on Code Project: http://www.codeproject.com/Tips/893609/CRUD-Many-to-Many-Entity-Framework, but this doesn't work for me either.
I'm trying to keep this as simple as possible.
I have two tables: dbo.Teacher and dbo.Student. Each has an "ID" column that servers as a primary key. I also have a third table called dbo.StudentTeacher which has exactly two columns, both are non-nullable and foreign keyed to the previous two tables; in other words, it establishes a many-to-many relationship between teachers and students. As expected, the EDMX designed shows only dbo.Student and dbo.Teacher and infers the relationship between them.
Here is a script for the above; there is nothing else in the database.
CREATE TABLE dbo.Teacher
(
Id INT NOT NULL PRIMARY KEY,
Name VARCHAR(MAX)
);
CREATE TABLE dbo.Student
(
Id INT NOT NULL PRIMARY KEY,
Name VARCHAR(MAX)
);
CREATE TABLE dbo.TeacherStudent
(
TeacherId INT NOT NULL FOREIGN KEY REFERENCES Teacher(Id),
StudentId INT NOT NULL FOREIGN KEY REFERENCES Student(Id)
);
INSERT INTO Teacher(Id, Name)
VALUES
(101, 'Tom');
INSERT INTO Student(Id, Name)
VALUES
(201, 'Sue'),
(202, 'Stan');
INSERT INTO TeacherStudent(TeacherId, StudentId)
VALUES
(101, 201);
Now that I've established my data structures, I want to accomplish a very simple task. From the script above, you can see that we have one teacher named "Tom" who has a student named "Sue". We also have a student named "Stan" with no teacher. My task is to modify the database so that Sue is no longer Tom's student and Stan becomes Tom's student.
To accomplish this, I wrote the following code:
class Program
{
static void Main(string[] args)
{
using (var entities = new TestEntities())
{
// There is only one teacher in the system.
Teacher teacher = entities.Teachers.Single();
// This teacher has a student #201: Sue.
// I want to replace her with student #202: Stan.
teacher.Students.Clear();
teacher.Students.Add(new Student() { Id = 202 });
entities.SaveChanges();
}
}
}
It looks very simple: clear the students associated with Tom and then add Stan as Tom's student. However, when I run the code, I get the following error: Unable to update the EntitySet 'TeacherStudent' because it has a DefiningQuery and no <DeleteFunction> element exists in the <ModificationFunctionMapping> element to support the current operation.
I tried simplifying the problem by trying to just remove Sue from being Tom's student without adding Stan, and I get the exact same error message.
As I understand, this error normally occurs when Entity Framework doesn't have enough information to do what you want it to do, but I really can't see what's missing. There are two simple tables with a join table between them and I need to be able to change which rows are related to which other rows.
I should also note that if I'm not mistaken, the change that I wish to make in this example should affect only the dbo.TeacherStudent table; the other two tables should not be touched.

Okay, after some more Google-Fu, I figured it out.
Even tho the join table must have only two columns with each column foreign keyed to the two tables to be related, the join table still needs a primary key, which can be a composite of the two foreign keys.
Thus, dbo.TeacherStudent should be created with this:
CREATE TABLE dbo.TeacherStudent
(
TeacherId INT NOT NULL FOREIGN KEY REFERENCES Teacher(Id),
StudentId INT NOT NULL FOREIGN KEY REFERENCES Student(Id),
PRIMARY KEY(TeacherId, StudentId)
);

Related

Database design with composite types in postgresql

How to refer another table built from composite type in my table.
I am trying to setup a database to understand postgresql and its Object oriented features.
The statement is as follows : There are multiple companies which can have board members.
Each company can own another company or a person can own that company too.
This is the type of database design I am looking for.
create type companyType(
name: VARCHAR,
boardMembers : personType[],
owns: companyType[]
)
create type personType(
name: VARCHAR,
owns: companyType[]
)
Create table company as companyType
Create table person as personType
I understand that I cannot self reference the companyType so I will probably move this another table.
My question is, when I am trying to insert into say company type, how do i insert list of person table objects as foreign key ?
Would making a column 'id' in each table and giving it type SERIAL work to use it as a foreign key?
That is not a relational database design, and you won't get happy with it.
Map each object to a table. The table columns are the attributes of the object. Add an artificial primary key (id bigint GENERATED ALWAYS AS IDENTITY). Don't use composite types or arrays.
Relationships are expressed like this:
If the relationship is one-to-many, add a foreign key to the "many' side.
If the relationship is many-to-many, add a "junction table" that has foreign keys to both tables. The primary key is the union of these foreign keys.
Normalize the resulting data model to remove redundancies.
Sprinkle with unique and check constraints as appropriate.
That way your queries will become simple, and you can use your database's features to make your life easier.

Entity Framework - How to Insert to table with foreign keys without retrieving foreign table rows first

I'm having a hard time finding the exact answer to this question, so my apologies if this is redundant.
So I have 3 tables defined such that:
Person :PersonId, FirstName, LastName
Company: CompanyId, CompanyName
Order: OrderId, PersonId, CompanyId
On the Order table, there is a foreign key defined on the PersonId and CompanyId columns, thus, my Order entity class generated by EF has a navigation properties of type Person (not PersonId) and Company.
So, to insert into the Order table, I first need to query the person and company tables to get the person and company entities. Then I can construct the Order object using the Person and Company entities and save it to the db.
In my scenario, I am being passed a PersonId and CompanyId.
In classic SQL I would just do INSERT INTO Order Set (CompanyId, PersonId) - 1 database call. But with EF, I have to do 3 db calls. This seems like overkill.
Is there any way around this?
PS - I'm using EF 6. I know I could generate an expression and make it single call..but that would still yield two subselects.
You can just include foreign key properties in addition to the navigation properties and then set them using the ids you have. If you do this will not have to go to the database to get related entities for just a sake of setting the relationship.

Entity Framework - Join table with composite key and a primary key

I am struggling with the way entity framework handles join tables, specifically because entity framework requires that a join table has a composite key composed of the primary keys on the two related entities I want the hold the relationship for. The problem here is that I need to hold a relationship to the relationship so to speak.
This may be a problem with my database design or equally due to my lack of understanding with EF. It is probably best illustrated through example (see below);
I have three tables each with a primary key:-
Table : DispatchChannel
{ *DispatchChannelID integer }
Table : Format
{ *FormatID integer }
Table : EventType
{ *EventTypeID integer }
The relationship between EventTypes and DispatchChannels is held in EventTypeDispatchChannels (see below) since this only contains a composite key it is not pulled through into our model and entity framework takes care of maintaining the relationship.
Table : EventTypeDispatchChannels
{ EventTypeID integer, DispatchChannelID integer
}
My problem now arises because for each combination of EventTypeID and DispatchChannelID I want to hold a list of available formats, this would be easy if my EventTypeDispatchChannels table had a primary key therefore my other join table would look like this;
Table : EventTypeDispatchChannelFormats
{ EventTypeDispatchChannelID integer, FormatID integer
}
The absence of a primary key on EventTypeDispatchChannels is where I am struggling to make this work, however if I had the key then entity framework no longer sees this as a linked entity.
I'm relatively new to C# so apologies if I have not explained this so well, but any advice would be appreciated.
The moment you want to give an association a more important role than just being a piece of string between two classes, the association becomes a first-class citizen of your domain and it's justified to make it part of the class model. It's also inevitable, but that's secondary.
So you should map EventTypeDispatchChannels to a class. The table could have its own simple primary key besides the two foreign keys. A simle PK is probably easier, so your table Format can do with a simple foreign key to EventTypeDispatchChannels for the one-to-many association.
You will lose the many to many feature to simply address dispatchChannel.Events. In stead you have to do
db.DispatchChannels.Where(d => d.DispatchChannelID == 1)
.SelectMany(d => d.EventTypeDispatchChannels)
.Select(ed => ed.Event)
On the other hand you have gained the possibility to create an association by just creating an EventTypeDispatchChannel and setting its primitive foreign key values. Many-to-many associations with a transparent junction table can only be set by adding objects to a collection (add an Event to dispatchChannel.Events). This means that the collection must be loaded and you need an Event object, which is more expensive in database round trips.

Setting the value of primary Key manually on Entity Model before insert

I have my Entity model where every entity has a primary key and they are marked with StoreGeneratedPattern = "Identity", the entity I am interested in is PEOPLE. It was created in oracle, and in another schema exists a "PEOLPE_HIST" table with it sequence. Before insert into PEOPLE I search on PEOPLE_HIST and if the person exists. I get the history information to including the ID (primary key) to insert into new PEOPLE table. I created a trigger for PEOPLE table to check if the ID is greater than or equal to 0, if it is, then I will not use the sequence and insert the Hist ID.
Is this possible?
thanks in advance

postgres ERROR: insert or update on table "xxxxx" violates foreign key contrain "xxxxx"

Hello
I have a main table BASECOMPANYDATA with BaseCompanyDataID as a PK. This is inhereted by
2 other tables CUSTOMERS & PRODUCTCOMPANIES. Now I have the table CONTACTS which I
want to connect with the 2 others as the customers and the productcompanies will have 0 or
more contacts. So I made a FK(BaseCompanyID) in CONTACTS and connected to the
BASECOMPANYDATA PK(BaseCompanyDataID). But when I am trying to insert a contact for
a record which exists in CUSTOMERS I get the following error:
ERROR: insert or update on table "xxxxx" violates foreign key contrain "xxxxx"
DETAIL: Key (BaseCompanyDataID)=(17) is not present in table "BaseCompanyData".
This ID exists in the above inherited table (BaseCompanyData).
Can someone explain why is this happening?
Thanks in advance
PS:Well, I have 4 tables:
1.BASECOMPANYDATA with BaseCompanyDataID as PK and some other fields.
2.CUSTOMERS which inherits from the above table so it has CustomerID as PK and has the fields of the BASECOMPANYDATA table namely BaseCompanyDataID etc.
3.PRODUCTCOMPANIES which inherits from BASECOMPANYDATA so it has the fields ProductCompanyID as PK and the fields of the inherited table like BaseCompanyDataID etc.
4.CONTACTS with ContactID as PK and BaseCompanyDataID as a FK. I tried to connect the table CONTACTS with 2 different ways. a. CONTACTS->BaseCompanyID with CUSTOMERS->BaseCompanyDataID and CONTACTS->BaseCompanyID with PRODUCTCOMPANIES->BaseCompanyDataID b. CONTACTS->BaseCompanyID with BASECOMPANYDATA->BaseCompanyDataID The result was the same error. Any answer on how I can create the FK using the inheritance, if there is. Thanks in advance
Did you read through the inheritance docs? Especially the 5.8.1. Caveats section?
http://www.postgresql.org/docs/9.0/static/ddl-inherit.html
...
Similarly, if we were to specify that cities.name REFERENCES some other table, this constraint would not automatically propagate to capitals. In this case you could work around it by manually adding the same REFERENCES constraint to capitals.
edit:
Inheritance is only half implemented in Postgsresql. If you want to save typing check out like in create table
In your first question I see the person recommended exactly the same thing I said. And now you have a problem? Hmm ...
This is pseudo sql I get from your repost:
base
baseid
customers(base)
baseid
id
products(base)
baseid
id
contacts
id
baseid references base(baseid)
Just do it the good old fashioned way!
base
id
customers
base_id references base(id)
id
products(base)
base_id references base(id)
id
contacts
id
base_id references base(id)