0

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

提前感谢您的回答。

4

2 回答 2

1

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

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

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

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

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

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

于 2013-05-29T08:46:35.920 回答
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; }
}

这种建模对象的方式被称为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; }
}

使用 fluent 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);
于 2013-05-28T21:13:26.927 回答