MVC EF代码首先创建模型类

时间:2013-05-28 20:48:33

标签: entity-framework model code-first

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

提前感谢您的回答。

2 个答案:

答案 0 :(得分:1)

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

  

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

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

  • DateTime属性的精度
  • 数字属性的精确度和比例
  • 固定长度的字符串或二进制属性
  • String属性为非unicode
  • 关系的删除行为
  • 高级制图策略

那就是说,我不是告诉你使用Fluent API而不是Data Annotation: - )

当您似乎在MVC应用程序上工作时,您应该记住,Entity Framework和MVC都会理解和处理Data Annotation属性以进行验证。但是MVC不会理解Fluent API的配置!

答案 1 :(得分:0)

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

这种调节对象的方式被称为普通的旧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; }
}

用流畅的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");
            });

使用流畅的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将无法处理这个新表。

在这种情况下,我们可以使用流畅的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);