我是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>
提前感谢您的回答。
答案 0 :(得分:1)
由于@Esteban已经为您提供了关于如何设计POCO并管理它们之间关系的非常详细的答案,我将只关注您问题的那一部分:
我应该如何使用数据注释或Fluent API声明关系
首先,您应该知道某些模型配置只能使用流畅的API完成,这里有一个非详尽的列表:
那就是说,我不是告诉你使用Fluent API而不是Data Annotation: - )
当您似乎在MVC应用程序上工作时,您应该记住,Entity Framework和MVC都会理解和处理Data Annotation属性以进行验证。但是MVC不会理解Fluent API的配置!
答案 1 :(得分:0)
您的Villa
和Apartment
类都有类似的属性,如果它们是但是,因为它是类型,您可以为此创建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; }
}
在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");
});
鉴于此模型:
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);