Entity Framework Mapping join table fields - c#

I have a join table that has a field in it that I need to get into an Entity and have it updatable. I have the Table setup below, the column I need is "PersonelleID" in the "Account" table. Now, there may be multiple, so in that case, there's a concept of primary (think of it as if you were a student who went from one school to another, you'd have the same account but multiple schools).
Any idea how I can bring this into the Entity world? Generating the database ignores this field on the join table (probably because it doesn't know where to put it).
Trying to see what the best route to go is.

if you are using the Code-First approach you would create an entity for the join table that has foreign keys to both Account and School and your extra properties.
public class Account
{
public int AccountId { get; set; }
public string UserName { get; set;}
}
public class AccountSchool
{
[ForeignKey("Account")]
public int AccountId { get; set; }
[ForeignKey("School")]
public string CEEBCodeId { get; set; }
public string PersonelleID { get; set; }
}
public class School
{
[Key]
public string CEEBCodeId { get; set; }
public string Name { get; set;}
}
This is how I've done it and here's is an article explaining how to do it as well:
http://www.itq.nl/blogs/post/Code-First-Entity-Framework-Additional-properties-on-many-to-many-join-tables.aspx

Related

Entity framework: Unable to define 1:1 relationship

I'd like to define relationship where Student can have only one favorite Course. I expect it would look like this in DB:
STUDENT
ID
Name
FavoriteCourseID
COURSE
ID
Name
How to achieve this with entity framework? I'd prefer to specify it just by attributes. I tried:
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public Course FavoriteCourse { get; set; }
public int? FavoriteCourseID { get; set; }
}
public class Class
{
public int ID { get; set; }
public string Name { get; set; }
}
which gave me this DB model:
STUDENT
ID
Name
FavoriteCourseID
COURSE
ID
Name
StudentID // how to remove this?
Note, that it may happen that several students have the same favorite class and therefore this is unacceptable solution.
Another question: what type of relationship this is? (1:1 / 1:N ?)
To specify 1 to 1 relationship, it is assumed, that primary key for the related entity matches the primary key of first entity. Also you should specify a virtual property to related entity:
public class Student
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public Course FavoriteCourse { get; set; }
public int? FavoriteCourseID { get; set; }
}
public class Class
{
[Key]
[ForeignKey("Student")]
public int ID { get; set; }
public string Name { get; set; }
public virtual Student Student { get; set; }
}
And it will be one-to-zero-or-one relationship. Check this tutorial.
If you will mark FavouriteCourse property with RequiredAttribute, it seems, that it will result in strong one to one relationship.
It will result in adequate database structure:
STUDENT
ID
Name
FavoriteCourseID
COURSE
ID
Name
However, if many students could have one favourite course, this structure will be a problem, as you want one-to-many instead of one-to-one. And you will have a duplicate records in database, because one course can refer only to one student. You have to think about your db design.
You can try this:
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
[ForeignKey("FavoriteCourseId")]
public Course FavoriteCourse { get; set; }
public int? FavoriteCourseId { get; set; }
}
Normally, you define one of the following relations:
Optional:Optional
Required:Optional
Optional:Many
Required:Many
Many:Many
Having Required:Required is not a usual relation, inserting the first entry with such a relation needs special treatment.
I Suppose you want Required:Many as in "Each student has one favorite course but many students may chose the same favorite course".

EF Code First - How do you specify foreign key name for child object table used by different type of parents

I've got some objects that look like this:
abstract public class Field
{
public int Id { get; set; }
public string Name { get; set; }
public int Ordinal { get; set; }
}
[Table("DropDownField")]
public class DropDownField : Field
{
public virtual List<FieldOption> Options { get; set; }
}
[Table("RadioButtonField")]
public class RadioButtonField : Field
{
public virtual List<FieldOption> Options { get; set; }
}
public class FieldOption
{
public int Id { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
In my database, it ends up creating the a FieldOptions table using Code First. However, it creates the following columns:
Id
Name
Value
DropDownField_Id
RadioButtonField_Id
What I'd like to see is just one Field_Id in this table since the Id of a field has to be unique across the different types of fields.
Is there a way to do this? I've done some searching but I must not know the right search terms to use to find the answer.
imho, what you want, from a relational database point of view, is a column (Option.FieldId) being a foreign key to 2 tables DropDownField and RadioButtonField.
That is whenever you insert an option, FieldId must reference an existing DropDownField AND an existing RadioButtonField.
That is at least weird.
I don't think this can/should be achieved.

Mapping optional to many relationship in Entity Framework

Some background: I inherited the database. Other applications are running against it, so I can't change the structure. We have a table of employees and a table of activities. Some of the employees are supervisors and the activities can optionally have a supervisor specified to indicate that only that particular supervisor can have their employees work that particular activity.
The way the database is set up, an employee is a supervisor if the SupID field is not null and that is the field that the SupID column in Activity refers to.
Here's a sample of the classes I'm working with:
public class Emp
{
public int EmpID { get; set; }
public string Fname { get; set; }
public string Lname { get; set; }
public int SupID { get; set; }
public virtual ICollection<Activity> SupervisedActivities { get; set; }
}
public class Activity
{
[Key]
public string ActNum { get; set; }
public int SupID { get; set; }
public virtual Emp Supervisor { get; set; }
}
The problem that I'm having is that no matter how I map the relationships between these two classes, EF wants to relate the SupID on Activity to the EmpID on Emp instead of the SupID. Is it possible to do what I'm trying to do in EF without modifying the database?
No you cannot do that.
Up to EF6 it's not possible to make a 1-to-many relation using an AK (alternate key) on the 1 side. The 1 side must always be the PK in the parent table.
MS has a site where you can vote for new EF features, and this is usually one of the top requested features: Unique Constraint (i.e. Candidate Key) Support
You can vote for it here, if you want.

EF Code first - Lazy Loading How to set up and access the joining table

public class Product
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public bool IsInStock { get; set; }
public string ImageUrl { get; set; }
public List<ProductOption> ProductOptions { get; set; }
public virtual Category Category { get; set; }
}
public class ProductOption
{
[Key]
public int Id { get; set; }
public string ProductOptionName { get; set; }
public string ProductOptionDescription { get; set; }
}
Now I know when your using Code First EF, so that the tables are created correctly. You need to do something like this.
modelBuilder.Entity<Product>().HasMany(p => p.ProductOptions).WithMany().Map(m =>
{
m.MapLeftKey("ProductId").MapRightKey("ProductOptionId").ToTable("SelectedProductOptionsInOrderedItem");
});
So....
Does this mean that if I do something like Product.ProductOptions I will be able to access all associated productoptions.
Is this the best way to set it up, or is there another way?
To enable lazy load and EF can create derived proxy types for your collection, that property should be declared this way:
public virtual ICollection<ProductOptions> ProductOptions { get; set; }
That should be enought. Other aspect is the mapping approach that you use. You choose fluent api, i prefer mapping by convention, but that is a matter of personal taste anyway.
Ok, Mapping by Conventions:
Is the ability of EF that from the name of entities and their properties along with their types, to map our model with the underlying data without providing any other information.
for example
public class Customer {
public long CustomerID {get; September;}
public string CustomerName {get; September;}
public Employee AssignedTo {get; September;}
}
With the previous model EF will map database with a table named Customer with:
. CustomerID bigint primary key column
. CustomerName nvarchar column
. Customer_EmployeeID foreign key to Employee table, with the datatype Corresponding to EmployeeID in that table.
You can read more Here

How to get Entity Framework Code First and nullable foreign key properties to work?

I'm trying to create a simple entity framework code first application. I have these classes:
public class User
{
public int UserId { get; set; }
public string Username { get; set; }
public virtual ActivationTicket ActivationTicket { get; set; }
}
public class ActivationTicket
{
public int ActivationTicketId { get; set; }
public virtual User User { get; set; }
public string Ticket { get; set; }
}
When I try to create a new user and save it to the database (a user without a ActivationTicket that is) I receive an exception
The INSERT statement conflicted with the FOREIGN KEY constraint "ActivationTicket_User". The conflict occurred in database "Test", table "dbo.ActivatioTickets", column 'ActivationTicketId'. The statement has been terminated.
I assume EF treats the mapping between User and ActivationTicket as 1-1 but it should be 1-0..1
What do I have to do to get this to work?
You will need a mapping rule like this:
modelBuilder
.Entity<User>()
.HasOptional<ActivationTicket>(u => u.ActivationTicket)
.WithOptionalPrincipal();
This will give you an ActivationTickets table with a UserId that is nullable.
#b3n
It should be enough to do this, at least with VS 2013:
public class User
{
public int UserId { get; set; }
public string Username { get; set; }
public int? ActivationTicketId { get; set;}
public virtual ActivationTicket ActivationTicket { get; set; }
}
This is the important part:
public int? ActivationTicketId { get; set;}
This will specify the foreignkey in your "User" table for the ActivasionTicket and define that it's optional.
credits go to:
http://forums.asp.net/t/1948351.aspx?Change+Foreign+Key+to+nullable+using+Code+First#5554732
I had the same problem and it instantly worked for me.
Also as a note i marked all my primary keys with the data annotation "[Key]". This might be necessary in order to make this work.

Categories