Entity framework code first relationship issue in a normalized schema - entity-framework

Its a simple question.
I have designed a project with a normalized database schema.
I am using code first.
I have a table called JOBS. I have another table called status. I intend to give a job a status. The status has to be user set so its in a table which you can add to. A job can be, say, "booked", "parts to be ordered", "invoiced". etc
As a POCO class I have the table STATUS with the following:
statusID (PK)
statusName
description.
In the JOBS table I would have a column called statusID as the foreign, non null key. EG
jobsID (PK)
clientID (FK)
statusID (FK)
jobTypeID (FK)
.
.
My question is, can I do this? Can I have a number of statelite tables (client, status, jobType) with names and descriptions and in the JOBS table there is a column with the satelite tables primary key as the column name?
I am confused as to what relationship this represents (one to one - one to many) and whether you can use the primary key of one table as the foreign key in the JOBS table when approaching this using Code First. Its not overly clear in the tutorials I have worked through.
Bottom line I want a specific job and be able to attach a specific status to it and in the view show the job with that status name and description...
Hoping someone might clear up the mud..
Simon

I think what you want to do are simple one-to-many relationships.
You have already defined this and everything looks fine for me.
But you can also add the Navigation property to your status class to make this one-to-many relationship more clear:
public List<Job> Jobs { get; set; }

Related

How to optionally persist secondary table in Eclipselink

I am working with Eclipselink and having issue with using secondary table.
I have two tables as below.
Student with columns student_id(Primary Key), student_name etc.
Registration with columns student_id(FK relationship with Student table), course_name (with not null constraint) etc.
The requirement is student may or may not have registration. If student has registration, the data should be persisted to Registration table as well. Otherwise only Student table should be persisted.
My code snippet is as below.
Student.java
------------
#Entity
#Table(name = "STUDENT")
#SecondaryTable(name = "REGISTRATION")
#Id
#Column(name = "STUDENT_ID")
private long studentId;
#Basic(optional=true)
#Column(name = "COURSE_NAME", table = "REGISTRATION")
private String courseName;
I tried the following scenarios.
1. Student with registration - Working fine. Data is added to both Student and Registration tables
2. Student without registration - Getting error such as 'COURSE_NAME' cannot be null.
Is there a way to prevent persisting into secondary table?
Any help is much appreciated.
Thanks!!!
As #Eelke states, the best solution is to define two classes and a OneToOne relationship.
Potentially you could also use inheritance, having a Student and a RegisteredStudent that adds the additional table. But the relationship is a much better design.
It‘s possible using a DescriptorEventListener. The aboutToInsert and aboutToUpdate callbacks have access to the DatabaseCalls and may even remove the statements hitting the secondary table.
Register the DescriptorEventListener with the ClassDescriptor of the entity. For registration use a DescriptorCustomizer specified in a Customizer annotation at the entity.
However, you will not succeed fetching the entities back again later on. EclipseLink uses inner joins when selecting from the secondary table, so that the row of the primary table will be gone in the results.

Database design with a single entity with many different units

I'm new to database design and I am working on a project that requires the use of a single entity (medication) that could be tied to any number of patients and each patient could have a different dosage. What would be the best way to layout a table for this type of situation. I could use a single table and just store each individual medication and dosage and tie that to the unique patient. But that would give me duplicate entries in the medication table (same med with just different dosage).
What I would like is to have a single entry for each medication name and have each patient have a unique dosage for that particular med. Of course a single patient could also have many different medications so I would have to be able to have a unique dosage for each med for different patients.
I using entity framework model first approach. Would I use a single table T_Patient_Medication and use each of the two table IDs as the primary key combo and then use a dosage field for that combination? If so how would I create the association to tie this table to the other two. Any suggestions?
Off the top of my head:
-a medication table(MedicineId, MedicineName, etc).
-a patient table(PatientId, PatientName, etc)
-a patient-medicine table(MedicineId, PatientId, Dosage, date, notes etc).
In other words, the medication table contains on row per unique med, a patient contains one row for each unique patient.
The patient-medicine table is where these two things meet: it contains a patientId, a medicineId and then anything else unique about that patient getting that medicine (i.e. Dr. name, dosage, date started etc). Personally I would make each row in the patient-medicine table also have its own unqiue ID separate from the combination of the patientid and medicine id (what are you going to do when the same patient goes back on the same medicine at a different time, if your primary key is Patientid+Medicineid). Each record should have its own unique id in my way of thinking.
There would be foreign keys between the tables to enforce this relationship: i.e. you can't add a row to the patient-medicine table unless the patientid exists in the patient table, and the medicine exists in the medicine table; and equally important prevent you from deleting a rows from tables where there are dependent records in other tables. If you take the time and setup all those foreign keys (relationships), it will be a breeze in EF to navigate the related records.
It is without a doubt more complicated than this, but that is the basics idea of a relational table.

Cannot get the Entity Framework to handle a GUID relationship

I am trying to achieve the following end result. My Person entity needs a collection of extra values and this collection of values will vary from Person instance to instance. I also have another Contact entity that likewise can have extra values form instance to instance.
Therefore I need three tables, a Person, Contact and an Extra where the Extra has the set of extra values for each Person and Contact instance that needs extra values. By giving the Person and Contact a GUID field it means that the GUID values will be unique across both tables and so I can use that as the field to join on. So I expect the definition to look like this...
Person
Id - int - Primary Key
Instance - GUID - Unique Constraint
Contact
Id - int - Primary Key
Instance - GUID - Unique Constraint
Extra
Id - int - Primary Key
Instance - GUID
Value - string
But I cannot model this into Entity Framework. I would like my Person and Contact entities to have a collection each that is the set of Extra values that are relevant to that entity. I create the three tables with the set of columns as indicated above.
But I cannot get the association to work as expected, it always wants to add extra columns to the database based on the primary key of the Person and Contact entities. Any ideas how to actually get this to work? Or maybe this is not possible in EF?
This is not possible with EF because it doesn't support unique keys. Only primary keys can be used as principal in relation.
As answered already, EF does not support unique keys. However, if you don't actually need to do anything with the Id property, it may suffice to tell EF that Instance is the primary key. EF doesn't really care whether it's the primary key at the database level, it merely needs to know whether it can use it as a key itself.
Edit: actually, that still wouldn't work. Besides not supporting unique keys, your Extra.Instance does not correspond to any fixed entity. In order to get it working, you would need to split the Extra table into PersonExtra and ContactExtra tables. That's probably a good idea regardless, as it allows you to add the foreign key constraints at the database level that correspond to those you wish to see in EF.
The EF way of doing this is to use a linking table - a simple table that has two columns, which will be not be visible in your model directly but the collections will be.
e.g.
Person
Id - int - Primary Key
Instance - GUID - Unique Constraint
Contact
Id - int - Primary Key
Instance - GUID - Unique Constraint
Extra
Id - int - Primary Key
Instance - GUID
Value - string
PersonExtra
PersonId - int
ExtraId - int
ContactExtra
ContactId - int
ExtraId - int
or change your Primary Key to be the GUID if your model will permit this.

Entity Framework Code First - Table Per Type Inheritance - Insertion Issue?

I'm having an issue inserting an instance of a subclass that inherits from a base class.
Consider the following code snippets from these POCOs:
public abstract class EntityBase<T>
{
private T _id;
[Key]
public T ID
{
// get and set details ommitted.
}
}
public abstract class PersonBase<T> : EntityBase<T>
{
// Details ommited.
}
public class Applicant : PersonBase<int>
{
// Details ommitted for brevity.
}
public class Employee : Applicant {}
Pretty standard inheritance right now. In our system, when an applicant finally becomes an employee, we collect extra data. If not hired, they remain an applicant with a limited set of information.
Now consider the fluent API that sets up the table-per-type inheritance model:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Set up table per type object mapping for the Visitor Hierarchy.
modelBuilder.Entity<Employee>().ToTable("Employees");
}
So far, so good...
If I look at the database this creates, I have a table named Applicants with an Id column of type int, auto-incrementing ID and I have an Employees table with an ID field as the primary key (non auto incrementing).
Basically, the ID field in the Employees table is a foreign key to the Applicants table.
This is what I want. I don't want a record into the Employees table corresponding to the Applicants table until they actually become an Employee.
The problem comes when I try to insert an Employee which comes down to this code:
public void PersistCreationOf(T entity)
{
DataContextFactory.GetDataContext().Set(typeof(T)).Add(entity);
}
The problem: It inserts a brand new applicant and Employee. I hooked it up to the Sql Profiler and looked at both insert queries that come down.
I want to just insert the Employee record with the ID it already has (the foreign key from the Visitors table).
I understand by default it needs to this: Obviously if you create a subclass and insert it, it needs to insert into both tables.
My question is is possible to tell the Framework - the base table already has information - just insert into the child table?
Thanks in advance!
Aside from sending raw SQL commands to insert the Employee minus Applicant properties fragment into the Employees table I believe it's impossible. You can either update or insert an entity. What you want is basically to update the base part of the Employee (or do nothing if nothing changed) and insert the derived part which is not possible.
Imagine what an ORM does: It maps key identities in the database to object identities in memory. Even in memory you couldn't achieve what you want: If you have an object in memory which is a Applicant, it is always an applicant. You cannot magically "upgrade" it to an Employee. You would have to create a new object of type Employee, copy the properties of the Applicant into the base properties of your new Employee and then delete the Applicant. The result is a new object with a new object identity.
I think you have to follow the same procedure in EF. Your Employee will be a new entity with new rows in both Applicant and Employee table and you need to delete the old Applicant. If you have autogenerated keys it will be a new identity with a new ID. (If you hadn't autogenerated keys you could supply the old ID again after deleting the old Applicant, thus "faking" an unchanged identity.) This will of course create big potential trouble if you have references to the old applicant with FK constraints.
Perhaps inheritance is not optimal for this scenario to "upgrade" an applicant into an employee. An optional navigation property (1-to-0...1 relationship) inside of the Applicant which refers to another entity containing the additional properties which make the applicant an employee would solve the problem. This navigation property could be set or not, letting you distinguish between an applicant and applicant which is also an employee. And you would not need to delete and change the ID of the applicant when you make it an employee.
(As said, "I believe". Maybe there is a hidden way, I didn't see.)

EF programmatically insert many to many

I have table with this structure ID PK and two columns with FK for example ActivityID and ContactID.
I try programmatically insert some value in this two FK columns.
How can I do this, any help is appriciated.Tnx
If you want to use your structure - you have to get instances of Activity and of Contact and just set corresponding properties on new entity.
var newActivityContact = new ActivityContact();// m_Entities.CreateActivityContact(0);
newActivityContact.Activity = activityRepository.GetById(activityId);
newActivityContact.Contact = contactRepository.GetById(contactId);
m_Entities.AddToActivityContact(newActivityContact);
m_Entities.SaveChanges();
I think the best solution would be to get rid of primary key, set up combination of ActivityID and ContactID as PK and then recreate whole model in visual designer. Every Activity object will have Contacts navigation property and every Contact will have Activities. You will be able to add contacts to activity by calling:
activity.Contacts.Add(contact);
If you really need additional ID, it will be more complicated.