EF Core code first Inheritance of separate table - entity-framework

Say I have a table Company defined in following entity:
public class Company
{
public Guid CompanyId { get; set; }
[Required]
public string Name { get; set; }
[MaxLength(50)]
public string Uid { get; set; }
...
}
And I need another table CompanyHistory what will have all fields of Company extended with CompanyHistoryId, EffectiveDate, DEffectiveDate.
I have tried it like this:
public class CompanyHistory : Company
{
public Guid CompanyHistoryId { get; set; }
public virtual Company { get; set; }
}
But instead of 2 tables migration makes one and combines all the columns.
How can I get same result without writing all the column again as is done here:
public class CompanyHistory
{
public Guid CompanyHistoryId { get; set; }
public Guid CompanyId { get; set; }
public virtual Company Company { get; set; }
[Required]
public string Name { get; set; }
[MaxLength(50)]
public string Uid { get; set; }
...
}

Related

EF code first model not in sync with database

My EF Code First model for some reason is not in sync with the db. I'm getting this error:
{"Invalid column name 'Type_Id1'."}
The field is actually called 'Type_Id' so I'm not sure from where that 1 comes up. I have the table column called as Type_Id and also I've added a Type_Id in my type entity model.
Why might I be getting that error message, plus why I'm getting 1 at the end of the name?
Update
My Task class:
public class Task
{
public Task()
{
Language = 1;
Grades = new HashSet<Grade>();
Categories = new HashSet<Category>();
Subjects = new HashSet<Subject>();
Rooms = new Collection<Room>();
Tools = new Collection<Tool>();
}
[Key]
public int Id { get; set; }
public string Description { get; set; }
public virtual TaskType Type { get; set; }
public string Rules { get; set; }
[Required]
[StringLength(200), MinLength(1)]
public string Name { get; set; }
public int PreperationTime { get; set; }
public int InstructionTime { get; set; }
public int TaskTime { get; set; }
public int Type_Id { get; set; }
public string VideoLink { get; set; }
[Required]
public int Language { get; set; }
public int? MinimumParticipants { get; set; }
public int? MaximumParticipants { get; set; }
public int? Rating { get; set; }
[Required]
public string CreatedBy { get; set; }
public virtual ICollection<Grade> Grades { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<Subject> Subjects { get; set; }
public virtual ICollection<Room> Rooms { get; set; }
public virtual ICollection<Tool> Tools { get; set; }
}
DBContext class:
public ApplicationDbContext() : base("DefaultConnection", false)
{
}
public DbSet<Task> Tasks { get; set; }
public DbSet<TaskType> TaskTypes { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
You need to add the FK attribute on your navigation property. EF is creating Type_Id1 because Type_Id already exists (although it can't tell by convention it is the FK).
[ForeignKey("Type_Id")]
public virtual TaskType Type { get; set; }
https://msdn.microsoft.com/en-us/data/jj591583.aspx#Relationships

EF one to many relation

I use EF's code first approach. I have the following three classes:
public class Inquiry
{
public Guid Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public virtual ApplicationUser CreatedBy { get; set; }
public virtual Contractor Contractor { get; set; }
public IList<ApplicationUser> InquiryUsers { get; set; }
public IList<InquiryComment> Comments { get; set; }
public IList<HydroTechEmail> Emails { get; set; }
public InquiryState State { get; set; }
public List<string> Attachments { get; set; }
public DateTime? TimeOfCreation { get; set; }
public DateTime? TimeOfModification { get; set; }
}
public class HydroTechEmail
{
public Guid Id { get; set; }
public string Subject { get; set; }
public string Content { get; set; }
public string FromDisplayName { get; set; }
public string FromAddress { get; set; }
public List<string> ToDisplayName { get; set; }
public List<string> ToAddress { get; set; }
public HydroTechEmailState State { get; set; }
public DateTime? ReceivedTime { get; set; }
public virtual List<HydroTechEmailAttachment> Attachments { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
public class ApplicationUser
{
public Guid Id {get;set;}
public string Firstname {get;set;}
public string Lastname {get;set;}
}
I thought EF will generate some intermediate classes for relation Inquiry -> Many Emails and Inquiry -> Many Application Users. Instead it created a foreign keys in ApplicationUser and HydroTechEmail classes to Inquiry class. How should I create this one to many relations?
The strange is that for Comments it created an intermediate table named InquiryComments.
Entity Framework will only generate intermediate tables for many-to-many relationships.
For one-to-many relationships, no intermediate tables will be created because it is not necessary.

EF Data Annotation - Foreign Key - How to Customize

My issue is the following. I have a Model for an Address table as follows.
public partial class ADDRESS
{
public ADDRESS()
{
this.ADDRESS_ID = Guid.NewGuid();
}
public Guid ADDRESS_ID { get; set; }
public string ADDRESS_LINE { get; set; }
public string CITY { get; set; }
public Guid? STATE_ID { get; set; }
public string ZIP { get; set; }
}
This ADDRESS model is used throughout my application and has different validation requirements depending on where it is placed within a form.
I am wondering if there is a way to customize the data annotations. For example, the ADDRESS_LINE and CITY properties are required for OCCUPATION_ADDRESS but not required for WORK_LOCATION_ADDRESS.
public class OCCUPATION_DETAILS
{
public string COMPANY_NAME { get; set; }
public string JOB_TITLE { get; set; }
etc...
public Guid OCCUPATION_ADDRESS_ID { get; set; }
public virtual ADDRESS OCCUPATION_ADDRESS { get; set; }
public WORK_LOCATION_ID { get; set; }
public virtual ADDRESS WORK_LOCATION_ADDRESS { get; set; }
}
Or it could be that basic validation is the same (zip has to be 5 digits), but I need to adjust the "DisplayName" that is used to match the label of the form it is within.
Trying to minimize the amount of copied models I have set up; otherwise maintenance will be a nightmare.
you can achieve this by using the idea of inheritance
how?
public abstract class ADDRESS
{
public ADDRESS()
{
this.ADDRESS_ID = Guid.NewGuid();
}
public Guid ADDRESS_ID { get; set; }
public string ADDRESS_LINE { get; set; }
public string CITY { get; set; }
public Guid? STATE_ID { get; set; }
public string ZIP { get; set; }
}
public parital class OCCUPATION_ADDRESS: ADDRESS,IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if(string.IsNullOrWhiteSpace(ADDRESS_LINE))
yield return new ValidationResult("Address line is required!",new string[]{"ADDRESS_LINE"});
}
}
public parital class WORK_LOCATION_ADDRESS: ADDRESS,IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
}
}
// and your Occupation details class will be like: instead of ADDRESS you will use the corresponding derived classes
public class OCCUPATION_DETAILS
{
public string COMPANY_NAME { get; set; }
public string JOB_TITLE { get; set; }
etc...
public Guid OCCUPATION_ADDRESS_ID { get; set; }
public virtual OCCUPATION_ADDRESS OCCUPATION_ADDRESS { get; set; }
public WORK_LOCATION_ID { get; set; }
public virtual WORK_LOCATION_ADDRESS WORK_LOCATION_ADDRESS { get; set; }
}
and the inheritance should be Table per Hierarchy (TPH)
for more information about TPH check this Table per hierarchy
hope that this will help you
regards

One to One with attributes EF codefirst

I am trying to link two models with One to One relationship
the classes are following:
public class Customer : BaseEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[ForeignKey("Account")]
public int AccountId { get; set; }
public virtual Account Account { get; set; }
[Required(AllowEmptyStrings = false)]
public string Address { get; set; }
[Required(AllowEmptyStrings = false)]
public string PublicName { get; set; }
[Required]
public int UserId { get; set; }
[ForeignKey("Id")]
[InverseProperty("Customer")]
public virtual User User { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
public class User : BaseEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[MaxLength(32)]
[RegularExpression(#"^[\w]+(\.?[\w\d_]+)?$")]
public string Login { get; set; }
[Required]
[MinLength(6)]
[DataType(DataType.Password)]
[RegularExpression(#"^[\w]+(\.?[\w\d_]+)?$")]
public string Password { get; set; }
[Required]
[StringLength(32)]
[DataType(DataType.EmailAddress)]
[RegularExpression(#"^([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$")]
public string Email { get; set; }
[Required]
public string Firstname { get; set; }
[Required]
public string Lastname { get; set; }
[MaxLength(256)]
public string ProfilePhoto { get; set; }
[Required]
[ForeignKey("Account")]
public int AccountId { get; set; }
[Required]
public virtual Account Account { get; set; }
[InverseProperty("User")]
public virtual ICollection<Rate> Rates { get; set; }
public int CustomerId { get; set; }
[ForeignKey("Id")]
[InverseProperty("User")]
public virtual Customer Customer { get; set; }
}
i searched did not but found solution for doing than ONLY with attributes. can anybody help me with that?
Thanks in advance!
The mistake that you're making is that you have both tables pointing to each other as having a foreign key relationship with the other. You have to pick one table as the base table and the other as being the one that has the FK in it. If you want the User table to be the base then you would do the following:
On the User class: Remove the [ForeignKey] and [InverseProperty] attributes from Customer.
On the Customer class:
[Key, ForeignKey("User")]
public int Id { get; set; }
//Other fields
public virtual User User { get; set; }

Entity Framework 4.3 CF many - to - many relationship saving object?

When creating many to many relationship using EF 4.3 code first approach, I cannot save data to connecting table, also cannot any examples on how to fill this table using saving object to Icollection... Here is my example:
MODELS
public class Hospital
{
//PK
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string County { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public Guid User_Id { get; set; }
//FK
public virtual ICollection<Operator> Operators { get; set; }
}
public class Operator
{
//PK
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Dob { get; set; }
public string Email { get; set; }
//FK
public virtual ICollection<Hospital> Hospitals { get; set; }
}
public class Project: DbContext
{
public DbSet<Hospital> Hospitals { get; set; }
public DbSet<Operator> Operators { get; set; }
}
CONTROLLER
public void AddOperater()
{
Hospital h = new Hospital();
h = db.Hospitals.Single(a=>a.Id ==1);
var o = new Operator();
o.FirstName = "John";
o.LastName = "Doe";
o.Dob = new DateTime(1988,2,12);
o.Email = "johndoe#gmail.com";
o.Hospitals.Add(h);
db.SaveChanges();
}
With this approach I keep getting error here: o.Hospitals.Add(h); even when my Hospital instance is filled with data. How exactly to save data to both tables, the dbo.Operators and dbo.OperatorHospital which is relationship table?
o.Hospitals.Add(h) will fail because the list is a null list. You cannot call Add() on a null list. Typically most people get around this by instantiating the list in the constructor of the entity... like so... the current line is blowing up due to a CSharp issue.
public class Hospital
{
//PK
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string County { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public Guid User_Id { get; set; }
//FK
public virtual ICollection<Operator> Operators { get; set; }
public Hospital()
{
Operators = new List<Operator>();
}
}
public class Operator
{
//PK
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Dob { get; set; }
public string Email { get; set; }
//FK
public virtual ICollection<Hospital> Hospitals { get; set; }
public Operator()
{
Hospitals = new List<Hospital>();
}
}