В каркасе сущностей столбцы таблиц представлены не виртуальными свойствами. Виртуальные свойства представляют отношения между таблицами (один-ко-многим, многие-ко-многим, ...)
Теперь все зависит от того, что вы хотите: могут ли две расширенные пользовательские информации иметь одно и то же изображение аватара, и если вы измените это изображение аватара, будет ли изменено изображение или все пользователи с этим аватаром?
Если это так, между Image и UserExtendedInfo существует отношение один ко многим: все изображения используются нулем илибольше UserExtendeInfos;каждый UserExtendedInfo имеет ровно одно изображение.
Если вы следуете соглашениям по кодированию Entity Framework, следующего будет достаточно для того, чтобы Entity Framework обнаружил это отношение «один ко многим» и назвал столбцы,и для обнаружения первичных ключей и внешних ключей.
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; }
}
Для полноты DbContext:
public class MovieDbContext : DbContext
{
public DbSet<Image> Images {get; set;}
public DbSet<UserExtendedInfo> UserExtendedInfos {get; set;}
}
Этого достаточно для структуры сущностей, чтобы обнаружить таблицы, столбцы в таблицахи связь между таблицами. Нет необходимости ни в аннотациях данных, ни в беглости API.
Существует небольшое отклонение от соглашений:
// Every UserExtendedInfo has exactly one Image, using foreign key
public int AvatarId {get; set;}
public virtual Image Image{ get; set; }
Если вы действительно хотите использовать Avatar
в качестве свойства, возможно, выможет потребоваться свободный API в 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);
Приведенный выше код говорит, что каждое изображение в таблице изображений имеет ноль или более UserExtendedInfos. Доступ ко многим можно получить с помощью свойства Image.UserExtendedInfos. Каждый UserExtendedInfo принадлежит ровно одному изображению (не ноль, не два, а ровно одно: обязательно). Доступ к этому изображению осуществляется через свойство UserExtendedInfo.Avatar. Внешний ключ к изображению, к которому принадлежит UserExtendedInfo, - это UserExtendedInfo.AvatarId.
Теперь, когда вы добавляете новый UserExtendedInfo, вы не можете SaveChanges, не указав ни для внешнего ключа правильное значение, ни для 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
});
Если вы хотите добавить новый Image и UserExtendedInfo за один шаг:
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 обнаруживает, что первичные ключи равны нулю, и, таким образом, объекты добавляются в базу данных. Из-за виртуальных свойств Entity Framework знает, что внешние ключи должны быть заполнены.