Many to zero relationship with Entity Framework - entity-framework-core

I have difficulty understand how I can make a "connecting" table between TimeLogEntity and TimeLogPeriodEntity (see classes below).
public class TimeLogEntity
{
public int Id {get; set;}
public DateTime Date { get; set; }
...
public TimeLogPeriodEntity TimeLogPeriod { get; set; }
}
public class TimeLogPeriodEntity
{
public int Id {get; set;}
public string Name {get; set; }
public DateTime From {get; set; }
public DateTime To {get; set; }
...
public ICollection<TimeLogEntity> TimeLogs{ get; set; }
}
I want EF to generate 3 tables: TimeLogs, TimeLogPeriods and TimeLogPeriodCrossTimeLogs,
I want a TimeLogPeriod to have multiple TimeLogs. But a TimeLog don't have to have a TimeLogPeriod.

Related

How do i create One-to-One mapping in EF 6 using Data Annotation approach

I am using EF 6.1.1.
I am unable to figure out how to create One-to-One relationship between two classes/tables with both entities have their owns PKs. I originally posted question link but could not get much help on it OR i am not able to get it. So, here i am putting my question in simple way.
Appreciate if someone can share thoughts on it.
My Requirement:
I would like create One-To-One relationship between Principle and Dependant with 'Id' from Principle class acts as Foreign Key in dependant class.
Principle Class
public class Student
{
public string FullName {get; set;}
}
Dependant Class
public class StudentReport
{
public string RollNumber { get; set; }
public string StudentType { get; set; }
}
Add PKs – EF requires this:
public class Student
{
public int Id { get; set; }
public string FullName { get; set; }
}
public class StudentReport
{
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
}
Note that EF 5 and later supports naming conventions: Id indicates a primary key. Alternately, it also supports the name of the class followed by "Id", so the above keys could have been StudentId for Student and StudentReportId for StudentReport, if you wished.
Add the foreign relation as a navigation property to at least one of the tables – in this case, you stated that StudentReport is the dependent, so let's add it to that one:
public class Student
{
public int Id { get; set; }
public string FullName { get; set; }
}
public class StudentReport
{
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public Student Student { get; set; }
}
Again – by naming convention – EF determines that a single Student property on StudentReport indicates that this is a navigational property associated with a foreign key. (By defining only the Student property, but no foreign key property, you are indicating that you don't care what EF names the associated FK ... basically, you're indicating you'll always access the related Student via the property.)
If you did care about the name of the FK property, you could add it:
public class Student
{
public int Id { get; set; }
public string FullName { get; set; }
}
public class StudentReport
{
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public int StudentId { get; set; }
public Student Student { get; set; }
}
Again – by naming convention – EF determines that StudentId is the FK associated with the Student property because it has the class name, "Student", followed by "Id".
All of this, so far, has been using conventions as defined in Entity Framework Code First Conventions, but Data Annotations are also an option, if you wish:
public class Student
{
[Key]
public int Id { get; set; }
public string FullName { get; set; }
}
public class StudentReport
{
[Key]
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
[ForeignKey("Student")]
public int StudentId { get; set; }
public Student Student { get; set; }
}
Doing this is actually a good idea, because it makes clearer your intent to other programmers that might not be aware of EF Conventions – but can easily infer them from simply looking at EF Data Annotations – and is still less cumbersome than Fluent API.
UPDATE
I just realized, I left this as a one-to-many, with enforcement of the one-to-one relationship being left to do in the code using this model. To enforce the one-to-one in the model, you could add a navigation property to the Student class going the other way:
public class Student
{
public int Id { get; set; }
public string FullName { get; set; }
public StudentReport StudentReport { get; set; }
}
public class StudentReport
{
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public Student Student { get; set; }
}
However, that's going to break, because EF doesn't know which entity to insert first on an add. To indicate which is dependent, you have to specific that the dependent class' PK is the FK to the principal class (this enforces one-to-one because – in order for a Student/StudentReport pair to be associated – their Id properties must be the exact same value):
public class Student
{
public int Id { get; set; }
public string FullName { get; set; }
public StudentReport StudentReport { get; set; }
}
public class StudentReport
{
[ForeignKey("Student")]
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public Student Student { get; set; }
}
or, using the full set of Data Annotations from earlier:
public class Student
{
[Key]
public int Id { get; set; }
public string FullName { get; set; }
public StudentReport StudentReport { get; set; }
}
public class StudentReport
{
[Key, ForeignKey("Student")]
public int Id { get; set; }
public string RollNumber { get; set; }
public string StudentType { get; set; }
public Student Student { get; set; }
}

EF Code first : set optional one to one relationship with data annotation

I've the following situation I try to solve : I've 2 tables, a Course table with some fields and a CourseDescription table which is optional (so Course may have a CourseDescription but CourseDescription must have a Course). I'm trying to set this up. So far, here's what I have :
public class Course
{
[Key, Column("Key_Course")]
public int ID { get; set; }
public string Name { get; set; }
public virtual CourseDescription CourseDescription { get; set; }
}
public class CourseDescription
{
[Key, ForeignKey("Course")]
public int ID { get; set; }
public string Description { get; set; }
public string PreRequis { get; set; }
public int CoursesID { get; set; }
[ForeignKey("CoursesID")]
public Course Course { get; set; }
}
This "works" meaning that EF doesn't complains about my model but the relation is not properly done because EF associate the PK of CourseDescription with the PK of Course. In my database, this is not the case (ex : CourseDescription.ID=1 is associated with CourseDescription.CoursesID=3, not 1).
Is there a way to fix that with data annotation ? I know I can use the fluent API but I don't want to override the model building just for that (unless there's no other way).
Thanks
Well, I think you have two choices:
Configure an one to many relationship
If you want to map the FK of the relationship between Course and CourseDescription, and you don't want to declare that FK property as Key of the CourseDescription entity, then, you don't have other choice that configure an one-to-many relationship. In that case your model would be like this:
public class Course
{
[Key, Column("Key_Course")]
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<CourseDescription> CourseDescriptions { get; set;}
}
public class CourseDescription
{
[Key]
public int ID { get; set; }
public string Description { get; set; }
public string PreRequis { get; set; }
[ForeignKey("Course")]
public int CourseID { get; set; }
public Course Course { get; set; }
}
Configure an one-to-one relationship but not map the FK of the
relationship
The only way that EF lets you map the FK in an one-to-one relationship is when the FK is declared as a PK too, so if you want to have diferent Ids in both entities and you want to stablish an one-to-one relationship, then you could do something like this:
public class Course
{
[Key, Column("Key_Course")]
public int ID { get; set; }
public string Name { get; set; }
public CourseDescription CourseDescription { get; set;}
}
public class CourseDescription
{
[Key]
public int ID { get; set; }
public string Description { get; set; }
public string PreRequis { get; set; }
[Required]
public Course Course { get; set; }
}
And work with the navigations properties.
It looks like you should not use ForeignKey attribute for ID property of CourseDescription class as you don't want to have an association between primary keys. Try to remove it.
Edit: It looks like I misunderstood the question previous time.
You can have your CourseDescription this way.
public class CourseDescription
{
[Key, ForeignKey("Course")]
public int ID { get; set; }
public string Description { get; set; }
public string PreRequis { get; set; }
public Course Course { get; set; }
}
In this case you don't need to have CoursesID field. Entities will be connected by primary keys.

Getting Error "The model backing the 'DBContext' context has changed since the database was created. "

I know This question is duplicate I found one solution too but this is four year old question and I think in these years the EntityFramework is on different level so I want to ask this question again. Here is the answer which I found and try to apply on entity Framework 5.0 but does not work
The model backing the <Database> context has changed since the database was created
here is my entity model classes first one is this
public class Student
{
public int StudentId {get; set;}
[StringLength(250),Required]
public string StudentName {get; set;}
[StringLength(20),Required]
public string Standard {get; set; }
[StringLength(250),Required]
public string Address {get; set; }
[StringLength(250),Required]
public string Emailid {get; set; }
[StringLength(12),Required]
public string Phoneno {get; set; }
}
and Second Model Class is this
public class Marks
{
public int MarksID { get; set; }
public int StudentId { get; set; }
public int English { get; set; }
public int Maths { get; set; }
public int Science { get; set; }
public int SocialStudy { get; set; }
public int Hindi { get; set; }
public int Total { get; set; }
public Student student { get; set; }
}
and this is my context class
public class DBContext:DbContext
{
public DBContext()
{
Database.SetInitializer<DbContext>(new DropCreateDatabaseAlways<DbContext>());
}
public DbSet<Student> TbStudent { get; set; }
public DbSet<Marks> TbMarks { get; set; }
}
I run this code and Getting this error
The model backing the 'DBContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).
Please expert help me regarding this issue
Code first migration will help you resolving the case.But to proceed in your way to initialize the database you must replace DbContext with DBContext(i.e with your context class) in the Database.SetInitializer function like this.
public class DBContext:DbContext
{
public DBContext()
{
Database.SetInitializer<DBContext>(new DropCreateDatabaseAlways<DBContext>());
}
}
Hope this helps.

issue in many to many relationship entity framework code first method

I have created an application in entityframework using code first method.
In application , there are two entities which have many to many relationship between them.
public class Course
{
[Key]
public int CourseId { get; set; }
public string Name { get; set; }
public ICollection<Student> Student{ get; set; }
}
public class Student
{
[Key]
public int StudentId { get; set; }
public string Name { get; set; }
public ICollection<Course> Course{ get; set; }
}
when I execute the project, it creates student table,Course table,StudentCourse table.
Now now the problem is,in StudentCourse table there are only two keys, StudentID and CourseId
I want to add additional column in that table how to do that ?
Declare a class defining that table:
public class Course
{
[Key]
public int CourseId { get; set; }
public string Name { get; set; }
public ICollection<Student> Student{ get; set; }
}
public class Student
{
[Key]
public int StudentId { get; set; }
public string Name { get; set; }
public ICollection<Course> Course{ get; set; }
}
public class StudentCourse
{
public int StudentId { get; set; }
public int CourseId { get; set; }
//More columns here
}

EF code first specify relationship table for a navigation property

I am new to EF code first and am trying to force an ICollection navigation property to use a specific relationship table I've manually created for mapping the entities.
The reason I am forced to do it is that I have a TenantId column on all my tables. Is this somehow possible?
[Table("Tenants")]
public class Tenant
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
// This should use ContactAddressesForTenants table
public virtual ICollection<Address> ContactAddresses {get; set;}
}
[Table("BusinessProfiles")]
public class BusinessProfile
{
[Key, ForeignKey("Tenant")]
public int TenantId { get; set; }
public virtual Tenant Tenant { get; set; }
// This should use the AddressesForBusinessProfiles table
public virtual ICollection<Address> ProfileAddresses { get; set; }
}
[Table("Addresses")]
public class Address
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("Tenant")]
public int TenantId { get; set; }
}
[Table("ContactAddressesForTenants")]
public class ContactAddressForTenant
{
[ForeignKey("Tenant")]
public int TenantId { get; set; }
[ForeignKey("Address")]
public int AddressId { get; set; }
public virtual Tenant Tenant { get; set; }
public virtual Address Address {get; set;}
}
[Table("AddressesForBusinessProfiles")]
public class AddressForBusinessProfile
{
[ForeignKey("BusinessProfile")]
public int TenantId { get; set; }
[ForeignKey("Address")]
public int AddressId { get; set; }
public virtual BusinessProfile BusinessProfile { get; set; }
public virtual Address Address { get; set; }
}
If I am understanding you correctly.
You can try changing this in your model.
Where it is:
// This should use ContactAddressesForTenants table
public virtual ICollection<Address> ContactAddresses {get; set;}
// This should use the AddressesForBusinessProfiles table
public virtual ICollection<Address> ProfileAddresses { get; set; }
Change to:
public virtual ICollection<ContactAddressForTenant> ContactAddresses {get; set;}
public virtual ICollection<AddressForBusinessProfile> ProfileAddresses { get; set; }