【问题标题】:MVC EF code first creating model classMVC EF 代码首先创建模型类
【发布时间】:2013-05-28 20:48:32
【问题描述】:

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

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

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 声明关系,然后请帮助我如何同时使用客户信息和属性信息更新客户表和属性表?

提前感谢您的回答。

【问题讨论】:

    标签: entity-framework model code-first


    【解决方案1】:

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

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

    首先,您应该知道某些模型配置只能使用 fluent API 来完成,这里有一个非详尽的列表:

    • DateTime 属性的精度
    • 数值属性的精度和小数位
    • 固定长度的字符串或二进制属性
    • 字符串属性为非 unicode
    • 关系的删除行为
    • 高级映射策略

    也就是说,我并不是要你使用 Fluent API 来代替 Data Annotation :-)

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

    【讨论】:

      【解决方案2】:

      您的VillaApartment 类都有相似的属性,如果它们是相同的但是因为它是类型,你可以为此创建一个enum

      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; }
      }
      

      这种建模对象的方式被称为plain old clr object或简称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; }
      }
      

      使用流利的 api 创建关系:

      多对多映射

      在您的OnModelCreating 方法上(从DbContext 派生时您将获得此虚拟方法):

      protected override void OnModelCreating(DbModelBuilder builder) {
          // Map models/table
          builder.Entity<User>().ToTable("Users");
          builder.Entity<Role>().ToTable("Roles");
      
          // Map properties/columns
          builder.Entity<User>().Property(q => q.UserId).HasColumnName("UserId");
          builder.Entity<User>().Property(q => q.Username).HasColumnName("Username");
          builder.Entity<Role>().Property(q => q.RoleId).HasColumnName("RoleId");
          builder.Entity<Role>().Property(q => q.Name).HasColumnName("Name");
      
          // Map primary keys
          builder.Entity<User>().HasKey(q => q.UserId);
          builder.Entity<Role>().HasKey(q => q.RoleId);
      
          // Map foreign keys/navigation properties
          // in this case is a many to many relationship
          modelBuilder.Entity<User>()
              .HasMany(q => q.Roles)
              .WithMany(q => q.Users)
              .Map(
                  q => {
                      q.ToTable("UserRoles");
                      q.MapLeftKey("UserId");
                      q.MapRightKey("RoleId");
                  });
      

      用fluent api映射不同类型的关系:

      一到零或一:

      鉴于此模型:

      public class MenuItem {
          public int MenuItemId { get; set; }
          public string Name { get; set; }
          public int? ParentMenuItemId { get; set; }
      
          public MenuItem ParentMenuItem { get; set; }
      }
      

      如果你想表达这种关系,你可以在你的 OnModelCreating 方法中这样做:

      builder.Entity<MenuItem>()
          .HasOptional(q => q.ParentMenuItem)
          .WithMany()
          .HasForeignKey(q => q.ParentMenuItemId);
      

      一对多

      鉴于此模型:

      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; }
      }
      

      您现在可能想要表达这种几乎显而易见的关系。你可以这样做:

      builder.Entity<Province>()
          .HasRequired(q => q.Country)
          .WithMany(q => q.Provinces)
          .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; }
          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; }
      }
      

      现在我们已经在连接表中添加了一个新属性 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);
      

      【讨论】:

      • 您的详细回答对我帮助很大,谢谢。但是我的问题的两个部分仍然没有得到回答。首先将子类放在父类中的可能性?并强制 EF 创建数据库。其次,我可以通过哪种机制更新彼此相关的表格?为了更清楚,我需要使用表格从用户那里收集数据,例如用户(或业主)的姓名等。同时他提供的物业信息,如类型和平方米等。将是存储在数据库中。抱歉这么苛刻。
      • 您可以这样做:firstUser.UserEmails.Add(createdUserEmail)。它支持通过导航属性添加、删除和编辑。这是 EF 的另一个优点。
      猜你喜欢
      • 1970-01-01
      • 2018-09-18
      • 2012-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多