In entity framework, the columns of the tables are represented by the non-virtual properties. The virtual properties represent the relations between the tables (one-to-many, many-to-many, ...)
Now it depends on what you want: can two user extended infos have the same Avatar image, and if you change this Avatar image, is the image or all users with this Avatar changed?
If so, There is a one-to-many relation between Image and UserExtendedInfo: Every Images is used by zero or more UserExtendeInfos; every UserExtendedInfo has exactly one Image.
If you follow the Entity Framework Coding conventions, the following will be enough for entity framework to detect this one to many relation, and to name the columns, and to detect the primary keys and the foreign keys.
public class Image
{
public int Id { get; set; } // by convention will become the primary key
public string ImgPath { get; set; }
// every Images is used by zero or more UserExtendedInfo (one-to-many)
public virtual ICollection<UserExtendedInfo> UserExtendedInfos {get; set;}
}
public class UserExtendedInfo
{
public int Id { get; set; } // by convention will become the primary key
public string FirstName { get; set; }
... // other non-virtual properties
// Every UserExtendedInfo has exactly one Image, using foreign key
public int AvatarId {get; set;}
public virtual Image Avatar { get; set; }
}
For completeness the DbContext:
public class MovieDbContext : DbContext
{
public DbSet<Image> Images {get; set;}
public DbSet<UserExtendedInfo> UserExtendedInfos {get; set;}
}
This is enough for entity framework to detect the tables, the columns in the tables and the relation between the tables. No need for data annotations nor fluent API.
There is a small deviation from the conventions:
// Every UserExtendedInfo has exactly one Image, using foreign key
public int AvatarId {get; set;}
public virtual Image Image{ get; set; }
If you really want to use Avatar
as property, it might be that you might need fluent API in OnModelCreating:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// one-to-many relation between Image and UserExtendedInfo:
modelBuilder.Entity<Image>()
.HasMany(image => image.UserExtendedInfos)
.WithRequired(userExtendedInfo => userExtendedInfo.Avatar)
.HasForeignKey(userExtendedInfo => userExtendedInfo.AvatarId);
The code above says that every Image in the Image table has zero or more UserExtendedInfos. The many can be accessed using propertie Image.UserExtendedInfos.
Every UserExtendedInfo belongs to exactly one Image (not zero, not two, exactly one: required). This one Image is accessed via property UserExtendedInfo.Avatar. The foreign key to the Image that the UserExtendedInfo belongs to is UserExtendedInfo.AvatarId.
Now whenever you add a new UserExtendedInfo, you can't SaveChanges without giving either the foreign key a proper value, or the Image:
var mickeyMouseImageId = myDbContext.Images
.Where(image => image.Name == "Mickey Mouse)
.Select(image => image.Id)
.FirstOrDefault();
// TODO: check that the image really exists, so result not zero
// Add a new UserExtendedInfo that uses mickey Mouse as Avatar:
var addedUserExtendedInfo = myDbContext.UserExtendedInfos.Add(new UserExtendedInfo()
{
// fill the foreign key:
AvatarId = mickeyMouseId,
... // other properties; don't fill the primary Key in Id
});
If you want to add a new Image and UserExtendedInfo in one step:
var addedUserExtendedInfo = myDbContext.UserExtendedInfos.Add(new UserExtendedInfo()
{
// don't fill the primary key nor the foreign key, you don't know their values yet
// add also a new Avatar
Avatar = new Image()
{
// don't fill the primary key, you don't know its value yet
... // other Image properties
// no need to fill the collection of Images
},
});
Entity framework detects that primary keys are zero, and thus the objects are added to the database. Because of the virtual properties, entity framework knows that foreign keys must be filled.