Entity framework MVC EF代码首先创建模型类

Entity framework MVC EF代码首先创建模型类,entity-framework,model,code-first,Entity Framework,Model,Code First,我是MVC和EF代码的新手。我正在努力使用EF代码优先的方法为房地产公司的DB模型建模,我做了一些练习,还阅读了一些在线教程 首先,我有一个客户表,该表与他/她注册为其所有者以出售或出租的一个或多个物业有关,我想知道是否有可能在注册物业的模型类中包含一些子类,如下所示: public Property { public int PropertyID { get; set; } public bool IsforSale { get; set; } public bool Isfor

我是MVC和EF代码的新手。我正在努力使用EF代码优先的方法为房地产公司的DB模型建模,我做了一些练习,还阅读了一些在线教程

首先,我有一个客户表,该表与他/她注册为其所有者以出售或出租的一个或多个物业有关,我想知道是否有可能在注册物业的模型类中包含一些子类,如下所示:

public Property
{

  public int PropertyID { get; set; }
  public bool IsforSale { get; set; }
  public bool IsforRent { get; set; }

  public class Apartment{

     public int ApartmentID { get; set; }
     public int AptSqureMeter { get; set; }
       .            .            .
       .            .            .

    }

  public class Villa{

     public int VillaID { get; set; }
     public int VillaSqureMeter { get; set; }
       .            .            .
       .            .            .

    }

    and also other sub-classes for other types of properties
}
如果答案是肯定的,那么我应该如何使用数据注释或Fluent API声明关系,然后请帮助我如何同时使用客户信息和属性信息更新客户表和属性表


提前感谢您的回答。

您的
别墅
公寓
类都有相似的属性,如果它们是相同的,但是是它的类型,您可以为此创建一个
枚举

public enum PropertyType {
    Apartment = 1,
    Villa
}

public class Property {
    public int PropertyID { get; set; }
    public bool IsforSale { get; set; }
    public bool IsforRent { get; set; }
    public PropertyType PropertyType { get; set; }
    public int SquareMeter { get; set; }
}
这种建模对象的方法简称为普通旧clr对象或POCO

假设此模型:

public class User {
    public int UserId { get; set; }
    public string Username { get; set; }

    public virtual List<Role> Roles { get; set; }
}

public class Role {
    public int RoleId { get; set; }
    public string Name { get; set; }

    public virtual List<User> Users { get; set; }
}
public class MenuItem {
    public int MenuItemId { get; set; }
    public string Name { get; set; }
    public int? ParentMenuItemId { get; set; }

    public MenuItem ParentMenuItem { get; set; }
}
public class Country {
    public int CountryId { get; set; }
    public string Name { get; set; }

    public virtual List<Province> Provinces { get; set; }
}
public class Province {
    public int ProvinceId { get; set; }
    public string Name { get; set; }
    public int CountryId { get; set; }

    public Country Country { get; set; }
}
public class User {
    public int UserId { get; set; }
    public string Username { get; set; }

    public virtual List<Role> Roles { get; set; }
    pubilc virtual List<UserEmail> UserEmails { get; set; }
}

pubilc class Email {
    public int EmailId { get; set; }
    public string Address { get; set; }

    public List<UserEmail> UserEmails { get; set; }
}

public class UserEmail {
    public int UserId { get; set; }
    public int EmailId { get; set; }
    public bool IsPrimary { get; set; }

    public User User { get; set; }
    public Email Email { get; set; }
}
使用fluent api映射不同类型的关系: 一对零或一: 鉴于这种模式:

public class User {
    public int UserId { get; set; }
    public string Username { get; set; }

    public virtual List<Role> Roles { get; set; }
}

public class Role {
    public int RoleId { get; set; }
    public string Name { get; set; }

    public virtual List<User> Users { get; set; }
}
public class MenuItem {
    public int MenuItemId { get; set; }
    public string Name { get; set; }
    public int? ParentMenuItemId { get; set; }

    public MenuItem ParentMenuItem { get; set; }
}
public class Country {
    public int CountryId { get; set; }
    public string Name { get; set; }

    public virtual List<Province> Provinces { get; set; }
}
public class Province {
    public int ProvinceId { get; set; }
    public string Name { get; set; }
    public int CountryId { get; set; }

    public Country Country { get; set; }
}
public class User {
    public int UserId { get; set; }
    public string Username { get; set; }

    public virtual List<Role> Roles { get; set; }
    pubilc virtual List<UserEmail> UserEmails { get; set; }
}

pubilc class Email {
    public int EmailId { get; set; }
    public string Address { get; set; }

    public List<UserEmail> UserEmails { get; set; }
}

public class UserEmail {
    public int UserId { get; set; }
    public int EmailId { get; set; }
    public bool IsPrimary { get; set; }

    public User User { get; set; }
    public Email Email { get; set; }
}
要表达这种关系,可以在
OnModelCreating
方法中进行:

builder.Entity<MenuItem>()
    .HasOptional(q => q.ParentMenuItem)
    .WithMany()
    .HasForeignKey(q => q.ParentMenuItemId);
builder.Entity()
.has可选(q=>q.ParentMenuItem)
.有很多
.HasForeignKey(q=>q.ParentMenuItemId);
一对多 鉴于这种模式:

public class User {
    public int UserId { get; set; }
    public string Username { get; set; }

    public virtual List<Role> Roles { get; set; }
}

public class Role {
    public int RoleId { get; set; }
    public string Name { get; set; }

    public virtual List<User> Users { get; set; }
}
public class MenuItem {
    public int MenuItemId { get; set; }
    public string Name { get; set; }
    public int? ParentMenuItemId { get; set; }

    public MenuItem ParentMenuItem { get; set; }
}
public class Country {
    public int CountryId { get; set; }
    public string Name { get; set; }

    public virtual List<Province> Provinces { get; set; }
}
public class Province {
    public int ProvinceId { get; set; }
    public string Name { get; set; }
    public int CountryId { get; set; }

    public Country Country { get; set; }
}
public class User {
    public int UserId { get; set; }
    public string Username { get; set; }

    public virtual List<Role> Roles { get; set; }
    pubilc virtual List<UserEmail> UserEmails { get; set; }
}

pubilc class Email {
    public int EmailId { get; set; }
    public string Address { get; set; }

    public List<UserEmail> UserEmails { get; set; }
}

public class UserEmail {
    public int UserId { get; set; }
    public int EmailId { get; set; }
    public bool IsPrimary { get; set; }

    public User User { get; set; }
    public Email Email { get; set; }
}
公共类国家{
public int CountryId{get;set;}
公共字符串名称{get;set;}
公共虚拟列表{get;set;}
}
公营省{
public int ProvinceId{get;set;}
公共字符串名称{get;set;}
public int CountryId{get;set;}
公共国家{get;set;}
}
你现在可能想表达这种几乎显而易见的关系。你可以这样做:

builder.Entity<Province>()
    .HasRequired(q => q.Country)
    .WithMany(q => q.Provinces)
    .HasForeignKey(q => q.CountryId);
builder.Entity()
.HasRequired(q=>q.Country)
.有许多(q=>q省)
.HasForeignKey(q=>q.CountryId);
以下是MSDN中的两个有用链接,以获取更多信息:

编辑:

我忘了提到如何创建具有附加属性的多对多关系,在这种情况下,EF将不会处理创建联接表的过程

鉴于这种模式:

public class User {
    public int UserId { get; set; }
    public string Username { get; set; }

    public virtual List<Role> Roles { get; set; }
}

public class Role {
    public int RoleId { get; set; }
    public string Name { get; set; }

    public virtual List<User> Users { get; set; }
}
public class MenuItem {
    public int MenuItemId { get; set; }
    public string Name { get; set; }
    public int? ParentMenuItemId { get; set; }

    public MenuItem ParentMenuItem { get; set; }
}
public class Country {
    public int CountryId { get; set; }
    public string Name { get; set; }

    public virtual List<Province> Provinces { get; set; }
}
public class Province {
    public int ProvinceId { get; set; }
    public string Name { get; set; }
    public int CountryId { get; set; }

    public Country Country { get; set; }
}
public class User {
    public int UserId { get; set; }
    public string Username { get; set; }

    public virtual List<Role> Roles { get; set; }
    pubilc virtual List<UserEmail> UserEmails { get; set; }
}

pubilc class Email {
    public int EmailId { get; set; }
    public string Address { get; set; }

    public List<UserEmail> UserEmails { get; set; }
}

public class UserEmail {
    public int UserId { get; set; }
    public int EmailId { get; set; }
    public bool IsPrimary { get; set; }

    public User User { get; set; }
    public Email Email { get; set; }
}
公共类用户{
public int UserId{get;set;}
公共字符串用户名{get;set;}
公共虚拟列表角色{get;set;}
publilc虚拟列表用户电子邮件{get;set;}
}
公共类电子邮件{
public int EmailId{get;set;}
公共字符串地址{get;set;}
公共列表用户电子邮件{get;set;}
}
公共类用户电子邮件{
public int UserId{get;set;}
public int EmailId{get;set;}
公共bool IsPrimary{get;set;}
公共用户{get;set;}
公共电子邮件{get;set;}
}
现在我们已经在联接表中添加了一个新属性,ef将不会处理这个新表

在这种情况下,我们可以使用fluent api实现这一点:

builder.Entity<UserEmail>()
    .HasKey( q => new {
        q.UserId, q.EmailId
    });

builder.Entity<UserEmail>()
    .HasRequired(q => q.User)
    .WithMany(q => q.UserEmails)
    .HasForeignKey(q => q.EmailId);

builder.Entity<UserEmail>()
    .HasRequired(q => q.Email)
    .WithMany(q => q.UserEmails)
    .HasForeignKey(q => q.UserId);
builder.Entity()
.HasKey(q=>new{
q、 UserId,q.EmailId
});
builder.Entity()
.HasRequired(q=>q.User)
.WithMany(q=>q.useremail)
.HasForeignKey(q=>q.EmailId);
builder.Entity()
.HasRequired(q=>q.Email)
.WithMany(q=>q.useremail)
.HasForeignKey(q=>q.UserId);

由于@Esteban已经为您提供了一个关于如何设计POCO和管理它们之间关系的非常详细的答案,我将只关注您问题的这一部分:

如何使用数据注释或Fluent API声明关系

首先,您应该知道,某些模型配置只能使用fluent API完成,下面是一个非详尽列表:

  • DateTime属性的精度
  • 数值特性的精度和比例
  • 作为固定长度的字符串或二进制属性
  • 作为非unicode的字符串属性
  • 关系的删除行为研究
  • 高级映射策略
也就是说,我并没有告诉您使用Fluent API而不是数据注释:-)


在处理MVC应用程序时,您应该记住,数据注释属性将由实体框架和MVC理解和处理,以便进行验证。但是MVC不会理解Fluent API的配置

你详细的回答对我帮助很大,谢谢。但我的问题还有两部分没有得到回答。首先,将子类放在父类中的可能性?并强制EF创建DB。第二,我可以通过哪种机制更新彼此相关的表?为了更清楚,我需要使用一个表单从用户那里收集数据,比如用户(或财产所有者)的姓名等。。同时,他还提供房产类型、面积等信息。。将存储在数据库中。很抱歉要求这么高。您可以这样做:
firstUser.UserEmails.Add(createdUserEmail)
。它支持通过导航属性添加、删除和编辑。这是英孚的另一个优点。