首页 > 技术文章 > 学习EF之CodeFirst二(数据库对应映射)

wujy 2013-09-21 15:09 原文

在上一篇文章我们简单通过一个实例完成对CodeFirst的理解,我们通过实体生成数据库里的表和字段,虽然有一些默认的配置生成规定,但其实我们可以能过对实体进一步控制从而对生成的表字段进行更加符合我们要求的控制;比如主键、非空、范围大小不、字段名称等等;主要有两种方式(1)Data Annotations(2)Fluent API

一:Data Annotations

此方法是利用在实体的那个属性里增加特性来进行操作控制;这些特性是在using System.ComponentModel.DataAnnotations下,要引用DLL

using System.ComponentModel.DataAnnotations;
namespace ModelLib
{
    public class Car
    {
        [Key]
        public int ID { get; set; }

        [Required(ErrorMessage="不能为空")]
        public string CarNum { get; set; }

        [StringLength(10,ErrorMessage="最大长度不能超过10个字符")]
        public string Colour { get; set; }

        [Range(1,10,ErrorMessage="UserYear取证范围在1-10之间")]
        public int UserYear { get; set; }

        [RegularExpression(@"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$")]
        public string Email { get; set; }
    }
}

假如我们代码没有按照上面规定来便会报出异常:

上面只是列出一部分的特性,其它特性可以查MSDN:http://msdn.microsoft.com/zh-cn/library/system.componentmodel.dataannotations.aspx

 

二:Fluent API(推荐使用,因为前一种范围有限)

1:我们可以在EF上下文里重写OnModelCreating然后对要设置的属性进行操作,但是这样一个实体类如果有3个属性需要配置,10个实体类就需要配置30个,那么就得在OnModelCreating方法里写30行,很麻烦且不易维护,所以一般不这么编写;

using System.Data.Entity;
using ModelLib;
namespace DataLibrary
{
    public class MyDbContext : DbContext
    {
        public MyDbContext()
            : base("name=MyTestDb")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Home>().HasKey(d => d.ID);
            modelBuilder.Entity<Home>().Property(d => d.Address).IsRequired();
            modelBuilder.Entity<Person>().Property(p => p.PassWord).HasMaxLength(50);
        }


        public DbSet<Person> Person { get; set; }

        public DbSet<Home> Home { get; set; }

        public DbSet<Car> Car { get; set; }
    }
}

2:注意返回值可以看出modelBuilder的Entity<>泛型方法的返回值是EntityTypeConfiguration<>泛型类。我们可以定义一个继承自EntityTypeConfiguration<>泛型类的类来定义domain中每个类的数据库配置。
ok,我们在DataAccess类库下新建一个继承自EntityTypeConfiguration<>泛型类的DestinationMap类,在构造函数里写上配置:

using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Text;
using ModelLib;
namespace DataLibrary
{
    public class HomeMap:EntityTypeConfiguration<Home>
    {
        public HomeMap()
        {
            Property(d => d.Address).IsRequired();
        }
    }
}
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Text;
using ModelLib;

namespace DataLibrary
{
    public class PersonMap:EntityTypeConfiguration<Person>
    {
        public PersonMap()
        {
            Property(d => d.Age).IsRequired();
        }
    }
}

然后修改EF上下文:

using System.Data.Entity;
using ModelLib;
namespace DataLibrary
{
    public class MyDbContext : DbContext
    {
        public MyDbContext()
            : base("name=MyTestDb")
        {
        }


        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new HomeMap());
            modelBuilder.Configurations.Add(new PersonMap());
        }

        public DbSet<Person> Person { get; set; }

        public DbSet<Home> Home { get; set; }

        public DbSet<Car> Car { get; set; }
    }
}

下面是一些常用的设置:

//【主键】
//Data Annotations:
[Key]
public int DestinationId { get; set; }

//Fluent API:
public class BreakAwayContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Destination>().HasKey(d => d.DestinationId);
    }
}

//【外键】
//Data Annotations:
public int DestinationId { get; set; }
[ForeignKey("DestinationId")]
public Destination Destination { get; set; }

//Fluent API:
modelBuilder.Entity<Lodging>().HasRequired(p => p.Destination).WithMany(p=>p.Lodgings).HasForeignKey(p => p.DestinationId);

//【长度】
//Data Annotations:通过StringLength(长度),MinLength(最小长度),MaxLength(最大长度)来设置数据库中字段的长度
[MinLength(10),MaxLength(30)]
public string Name { get; set; }
[StringLength(30)]
public string Country { get; set; }

//Fluent API:没有设置最小长度这个方法
modelBuilder.Entity<Destination>().Property(p => p.Name).HasMaxLength(30);
modelBuilder.Entity<Destination>().Property(p => p.Country).HasMaxLength(30);

//【非空】
//Data Annotations:
[Required(ErrorMessage="请输入描述")]
public string Description { get; set; }

//Fluent API:
modelBuilder.Entity<Destination>().Property(p => p.Country).IsRequired();

//【数据类型】
Data Annotations:
将string映射成ntext,默认为nvarchar(max)
[Column(TypeName = "ntext")]
public string Owner { get; set; }

//Fluent API:
modelBuilder.Entity<Lodging>().Property(p => p.Owner).HasColumnType("ntext");

//【表名】
//Data Annotations:
[Table("MyLodging")]
public class Lodging
{
}

//Fluent API
modelBuilder.Entity<Lodging>().ToTable("MyLodging");

//【列名】
//Data Annotations:
[Column("MyName")]
public string Name { get; set; }

//Fluent API:
modelBuilder.Entity<Lodging>().Property(p => p.Name).HasColumnName("MyName");

//【自增长】
//Data Annotations
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]  Guid类型的主键、自增长
public Guid SocialId { get; set; }

//Fluent API:
modelBuilder.Entity<Person>().Property(p => p.SocialId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

//【忽略列映射】
//Data Annotations:
[NotMapped]
public string Name
{
    get
    {
        return FirstName + " " + LastName;
    }
}

//Fluent API:
modelBuilder.Entity<Person>().Ignore(p => p.Name);

//【忽略表映射】
//Data Annotations:
[NotMapped]
public class Person
{ }

//Fluent API:
modelBuilder.Ignore<Person>();

//【时间戳】
//Data Annotations:Timestamp
[Timestamp]
public Byte[] TimeStamp { get; set; }   只能是byte类型

//Fluent API:
modelBuilder.Entity<Lodging>().Property(p => p.TimeStamp).IsRowVersion();

//【复杂类型】
//Data Annotations:
 [ComplexType]
 public class Address
 {
     public string Country { get; set; }
     public string City { get; set; }
 }

//Fluent API:
modelBuilder.ComplexType<Address>();

 

 

推荐阅读