简体   繁体   English

实体框架。 保存和读取后字段值为 null

[英]Entity Framework. Field value is null after save and read

I have a problem with EF.我对 EF 有疑问。 May I misunderstand something.... So i have a simple model:我可能会误解一些东西......所以我有一个简单的model:

public class Image
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string ImgPath { get; set; }
}

public class UserExtendedInfo
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string UserEmail { get; set; }
    public Image Avatar { get; set; }
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<UserExtendedInfo>().HasRequired(r => r.AvatarPath);
}

After creating new Image object and adding it to context and save it, I can see new row in Images and UserExtendedInfoes tables.创建新图像 object 并将其添加到上下文并保存后,我可以在图像和 UserExtendedInfoes 表中看到新行。 In user table I can see column Avatar_id that has id of needed row of Images table.在用户表中,我可以看到列 Avatar_id 具有所需图像表行的 id。 But when I try to load UserExtendedInfo from database - avatar field is null....但是当我尝试从数据库加载 UserExtendedInfo 时 - 头像字段是 null....

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;如果是这样,那么 Image 和 UserExtendedInfo 之间存在一对多的关系:每个 Images 都被零个或多个 UserExtendedInfo 使用; every UserExtendedInfo has exactly one Image.每个 UserExtendedInfo 都只有一个 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:为了完整性,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.不需要数据注释,也不需要流利的 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:如果你真的想使用Avatar作为属性,可能需要在 OnModelCreating 中使用 fluent API:

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.上面的代码表明 Image 表中的每个 Image 都有零个或多个 UserExtendedInfos。 The many can be accessed using propertie Image.UserExtendedInfos.许多可以使用属性 Image.UserExtendedInfos 访问。 Every UserExtendedInfo belongs to exactly one Image (not zero, not two, exactly one: required).每个 UserExtendedInfo 恰好属于一个 Image(不是零,不是两个,正好是一个:必需)。 This one Image is accessed via property UserExtendedInfo.Avatar.这个图像是通过属性 UserExtendedInfo.Avatar 访问的。 The foreign key to the Image that the UserExtendedInfo belongs to is UserExtendedInfo.AvatarId. UserExtendedInfo 所属的Image 的外键是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:现在,每当您添加新的 UserExtendedInfo 时,如果不给外键一个适当的值或图像,您就无法 SaveChanges:

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:如果您想一步添加新的 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 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.由于虚拟属性,实体框架知道必须填写外键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM