When I have two models with one to many relationship, they look like the models below:
public class Student
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int StudentID { get; set; }
public string Name { get; set; }
public int ClassID { get; set; }
[ForeignKey("ClassID")]
public virtual Class Class { get; set; }
}
public class Class
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ClassID { get; set; }
public string Name { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
This means that I can use the include method to get the related data. Now I work on a project with more than 600 tables. For these tables there are no relationships and I can not create relationships between the tables. Is there a way to link the models somehow so that I will be able to get the related data?
Yes, you can join tables without Relationships in Model Classes.
For example assume you have TeacherId in both of your tables Student and Class
You can join two tables based on TeacherId as follows
DbContext.Students
.Join(DbContext.Classes,student=>student.TeacherId,class=>class.TeacherId, (std,tchr)=> new {std,tchr});
Related
I have two tables: Place, and MenuSection, that currently have a one-to-many relationship defined like so:
public class Place
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public int PlaceID { get; set; }
public virtual ICollection<MenuSection> MenuSections { get; set; }
}
public class MenuSection
{
[Key]
public int MenuSectionID { get; set; }
public int PlaceID { get; set; }
}
However, I now need a many-to-many relationship. If I was just starting out then this would be achieved by changing the MenuSection class to look like this:
public class MenuSection
{
[Key]
public int MenuSectionID { get; set; }
public virtual ICollection<Place> Places { get; set; }
}
The problem is I already have vast amounts of data and business logic associated with the current relationship. So I figure I'll have to leave the PlaceID property in for now and add the places collection.
My question then is: how do I then tell EF the relationship is now many-to-many and to populate the auto-generated joining table with the existing relationships so that I can then remove the PlaceID property from the MenuSection class?
Alternatively I suppose I could manually create a joining table and rewrite all the business logic, manually move the existing relationships over and rewrite all the business logic like so:
public class Place
{
[Key]
[ForeignKey("Place")]
public int PlaceID { get; set; }
[Key]
[ForeignKey("MenuSection")]
public int MenuSectionID { get; set; }
public virtual Place Place { get; set; }
public virtual MenuSection MenuSection { get; set; }
}
I'm surprised this question hasn't been asked before so I just wanted to check I haven't missed a trick?
I have an abstract superclass which contains a [Key] field.
That class is then extended by 2 different classes which share this [Key] field, but have some fields of their own also.
But the problem is, when I create 2 DbSet<> objects for these 2 extending classes, they get put in the same table, and their fields get combined into that table.
So in my Context class, I have defined these:
DbSet<EmployeeAccount> EmployeeAccounts;
DbSet<PatientAccount> PatientAccounts;
I was expecting a separate table for each of these entities, but I got just 1 big table, and both EmployeeAccounts and PatientAccounts work with that 1 table (this leaves me with couple of columns in every row being empty).
I'm guessing this is happening because PatientAccount and EmployeeAccount have the same [Key] from their superclass.
Abstract class is really simple and looks like this:
public abstract class UserAccount : Entity<int>
{
[Key]
public int Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
Extending classes are the following:
public class EmployeeAccount : UserAccount
{
[ForeignKey("Employee")]
public int EmployeeId { get; set; }
public Employee Employee { get; set; }
[Column(TypeName = "nvarchar(24)")]
public EmployeeType EmployeeType { get; set; }
}
and
public class PatientAccount : UserAccount
{
[ForeignKey("Patient")]
public int PatientId { get; set; }
public Patient Patient { get; set; }
public IEnumerable<FavoriteDoctor> FavouriteDoctors { get; set; }
}
Am i doing something wrong, or is this the expected behaviour?
If expected, is there a way for me to say to the EF to create 2 separate tables for these entities, even though they share the same [Key] field and superclass?
Thanks in advance.
I am new to entity framework and I am using code first approach to create entities using TPT inheritance.
My requirement is to create the entities as per the attached diagram where ID is PK for Customers table and FK for the AddressDetails and ContactDetails table. Based on the keys I also need to create the association and navigation properties for the entities. Table Diagram
In my code I have created entities as
public class Customer
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int ZipCode { get; set; }
public virtual ContactDetails ContactDetails { get; set; }
public virtual AddressDetails AddressDetails { get; set; }
}
[Table("ContactDetails")]
public class ContactDetails: Customer
{
public string MobileNo { get; set; }
public string EmailId { get; set; }
}
[Table("AddressDetails")]
public class AddressDetails: Customer
{
public string BillingAddress { get; set; }
public string DeliveryAddress { get; set; }
}
My question is, have I created the association and navigation properties correctly or do I need to add them in the ContactDetails and AddressDetails class as well? Also, when I run the code the entities are getting created in the database but for the Customer table there are 2 additional columns created as AddressDetails_Id(FK,int,null) and ContactDetails_Id(FK,int,null). I think they are created because of the navigation property but I do not need these columns in the database to be created. Also the values are always null in these two columns.
Any help would be appreciated. Thanks in advance.
I have the following CodeFirst Classes. I am trying to model a TPT structure here. An user can login and access his Individual profile or his many company profiles. Individual and Company have polymorphic association with other tables.
public class LoginDetail
{
public int Id { get; set; }
//Other Properties
public virtual Individual Individual { get; set; }
public virtual ICollection<Company> Companies{ get; set; }
}
public abstract class Profile
{
public int Id { get; set; }
//Other Properties
public virtual int LoginId { get; set; }
public virtual LoginDetail Login{ get; set; }
}
[Table("Individuals")]
public class Individual : Profile
{
//Other Properties
}
[Table("Companies")]
public class Company: Profile
{
//Other Properties
}
This maps to LoginDetails, Profiles, Individuals and Companies Table. Everything works fine but in order to associate one-to-many relation between LoginDeatils and Companies it creates an extra LoginDetail_Id in Companies Table. This breaks other parts of my model. How do i tell entity framework to use LoginId in Profiles Table for both the one-to-one relation between LoginDeatils and Individuals and one-to-may relation between LoginDeatils and Companies
you should use InverseProperty and ForeignKey attribute ,
try this code :
public class LoginDetail
{
public int Id { get; set; }
//Other Properties
public virtual Individual Individual { get; set; }
[InverseProperty("Login")]
public virtual ICollection<Profile> Profiles{ get; set; }
}
public abstract class Profile
{
public int Id { get; set; }
//Other Properties
public virtual int LoginId { get; set; }
[InverseProperty("Profiles")]
[ForeignKey("LoginId")]
public virtual LoginDetail Login{ get; set; }
}
I have a User and an Organization class. They look like this
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Organization> Organizations { get; set; }
}
public class Organization : EntityBase
{
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<User> Users { get; set; }
}
And both inherit from an EntityBase class to get common fields like Id and created/updated tracking.
public abstract class EntityBase
{
public int Id { get; set; }
public DateTime Created { get; set; }
public virtual User CreatedBy { get; set; }
public DateTime Updated { get; set; }
public virtual User UpdatedBy { get; set; }
}
As denoted by the ICollection properties on both, there should be a many-to-many relation. However when my database is autogenerated I get incorrect foreign keys added to my tables
If I change the CreatedBy and UpdatedBy to be strings instead of User properties I get a join table, which is what I was looking for.
Is this a matter of Entity Framework simply being confused and I need to supply many-to-many configuration in the using fluent mappings, or have I done something wrong?
If you have multiple relationships you need to configure them manually by fluent API or using attributes,
Note:If you have multiple relationships between the same types (for
example, suppose you define the Person and Book classes, where the
Person class contains the ReviewedBooks and AuthoredBooks navigation
properties and the Book class contains the Author and Reviewer
navigation properties) you need to manually configure the
relationships by using Data Annotations or the fluent API
Here is the article from Microsoft.