MVC EF code first creating model class

ⅰ亾dé卋堺 提交于 2020-01-07 06:36:31

问题


I'm new to MVC and EF code first. I'm in struggle to model a real-estate company DB model using EF code-first approach and I did some exercises as well as reading some online tutorials.

First thing I have a customers table that would be in relation with one or more properties he/she has registered as it's owner to sell or to rent, I was wondering if it is possible to have some sub classes inside a model class for registered properties as below:

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
}

If the answer is Yes, then how should I declare the relations using data annotation or Fluent API, and then please help me how to update both Customers table and Property table with the customer information and property info at the same time?

thanks for your answer in advance.


回答1:


As @Esteban already provided you with a pretty detailed answer on how to design your POCOs and manage the relationship between them, I will only focus on that part of your question:

how should I declare the relations using data annotation or Fluent API

First of all, you should know that certain model configurations can only be done using the fluent API, here's a non exhaustive list:

  • The precision of a DateTime property
  • The precision and scale of numeric properties
  • A String or Binary property as fixed-length
  • A String property as non-unicode
  • The on-delete behavior of relationships
  • Advanced mapping strategies

That said, I'm not telling you to use Fluent API instead of Data Annotation :-)

As you seem to work on an MVC application, you should keep in mind that Data Annotation attributes will be understood and processed by both by Entity Framework and by MVC for validation purposes. But MVC won't understand the Fluent API configuration!




回答2:


Both your Villa and Apartment classes have similar properties, if they are the same but as it's type, you could create an enum for that.

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

This way of modelating objects is refered as plain old clr object or POCO for short.

Assume this model:

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

Creating relations with fluent api:

Mapping many to many

On your OnModelCreating method (you'll get this virtual method when deriving from 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");
            });

Mapping different types of relationships with fluent api:

One to zero or one:

Given this model:

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

    public MenuItem ParentMenuItem { get; set; }
}

And you want to express this relationship, you could do this inside your OnModelCreating method:

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

One to many

Given this model:

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

You now might want to express this almost obvious relationship. You could to as follows:

builder.Entity<Province>()
    .HasRequired(q => q.Country)
    .WithMany(q => q.Provinces)
    .HasForeignKey(q => q.CountryId);

Here are two useful links from MSDN for further info:

  • Configuring Relationships with the Fluent API.
  • Code First Relationships Fluent API.

EDIT:

I forgot to mention how to create a many to many relationship with additional properties, in this case EF will NOT handle the creation of the join table.

Given this model:

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

Now that we've added a new property into our join table ef will not handle this new table.

We can achieve this using the fluent api in this case:

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


来源:https://stackoverflow.com/questions/16801245/mvc-ef-code-first-creating-model-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!