zoukankan      html  css  js  c++  java
  • Entity Framwork CodeFirst 学习笔记二:约定和配置

    对EF Code first 编程模型有了一定的了解之后,通过上一篇简单的例子,通过代码对数据库进行了创建,但是其数据结构都是按照EF默认的约定来创建的。比如:

    数据库名称:由于上一篇的例子在配置文件中显示设置数据库的连接,因此创建的数据库名称就为连接串中指定的 BookDb。若没有显示指定的话,并使用默认数据库 .\SQLEXPRESS, 则EF生成的数据库名称应该为DbContext 的"命名空间.类名" (DataAccess.BookContext)

    表名:默认约定均为模型类名的复数形式。如例子中的 AuthorsBooks ,没有指定架构名称则采用默认架构名:dbo

    数据类型:字符串类型默认映射成nvarchar(max),byte[] 数组类型默认映射成varbinary(max),bool类型默认映射成bit,decimal类型默认映射成decimal(18, 2),float类型默认映射成float。由于bool,decimal,float等是值类型,不能为给他们分配Null值。因此生成的数据库会要求对应的列非空。 

    外键:codefirst 会自动检测模型间的关系,比如我们的实体类中Author 有 List<Books> 属性,Book类中还有 Author 属性,则说明 Author 和Book 是 1对多的关系,EF中外键的命名默认是导航属性名(这里是Author_对应主表的主键)由于我们有了AuthorId ,因此就AuthorId 就默认为外键。

    上一篇的例子均是采用EF Code First 的默认配置,下面我们来对这些配置进行修改,有两种方式可以打破默认的配置规则:

    • Data Annotations (需引用System.ComponentModel.DataAnnotations),直接作用于类的属性上面。
    • 利用FluntAPI,通过增加相应的配置类来覆盖默认配置。

    如果使用FluntAPI,需要在上下文类中增加如下方法:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
         //这里增加配置代码
    
          base.OnModelCreating(modelBuilder);
    }

     注意 FluntAPI 优先于 Data Annotations 配置。

    在《Programming Entity Framework Code First》 这本书中将 配置约定分别分为了三个章节,分别是属性配置、关系配置和数据库映射配置。下面分别对常用的配置做一下总结:

    1、表名及架构名:(不指定架构名,则默认为dbo)

    Data Annotations 方式:[Table]

    [Table("T_Author", Schema = "Lx")]
     public class Author
     {
        public int AuthorId { get; set; }
        public string Name { get; set; }
        public DateTime Birthday { get; set; }
        public byte[] Photo { get; set; }
        public string Introduce { get; set; }
        public List<Book> MyBooks { get; set; }
     }

    Flunt API 方式:

    modelBuilder.Entity<Author>().ToTable("T_Author", "Lx");

      2、字段名:

    Data Annotations 方式:[Column]

    [Column("AuthorName")]
    public string Name { get; set; }

    Flunt API 方式:

    modelBuilder.Entity<Author>().Property(a => a.Name).HasColumnName("AuthorName");

     3、主键:

    Data Annotations 方式:[Key] 

    [Key]
    public int AuthorId { get; set; }

     Flunt API 方式:

    modelBuilder.Entity<Author>().HasKey(a=>a.AuthorId);

     4、外键:

    Data Annotations 方式:[ForeignKey] 

    public int AuthorId { get; set; }
    [ForeignKey("AuthorId")]
    public Author Author { get; set; }

     注意:如果ForeignKey中指定了列名 ,如“AuthorId ”则类中必须存在 AuthorId 属性

    Flunt API 方式:

     modelBuilder.Entity<Book>().HasRequired(b => b.Author).WithMany(a => a.MyBooks).HasForeignKey(b => b.AuthorId);

     5、设置自动增长属性  

    利用数据生成项 DatabaseGenerated,它后有三个枚举值: Identity:自增长;None:不处理;Computed:表示这一列是计算列

    注意:在EF中,如果主键是int类型,Code First生成数据库的时候会自动设置该列为自增长。但如果主键是Guid类型,需要手动去设置 

    DATA Annotations 方式:[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 

    [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int AuthorId { get; set; }

     Flunt API 方式: 

    modelBuilder.Entity<Author>().HasKey(a => a.AuthorId).Property(a => a.AuthorId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

      关于 DatabaseGenerated 后面的文章要详细的学习

    6、忽略映射

    对于不需要映射的表或者列,我们可以忽略映射

    Data Annotations 方式:[NotMapped] 

    //忽略表映射
    [NotMapped]
    public class Book
    {
       public int BookId { get; set; }
       public string BookName { get; set; }
       public decimal Price { get; set; }
       public bool IsSellFast { get; set; }
       public int AuthorId { get; set; }
       public Author Author { get; set; }
    }
    //忽略列映射
    [NotMapped]
    public bool IsSellFast { get; set; }

     Flunt API 方式:

    //忽略表映射
    modelBuilder.Ignore<Book>();
    //忽略列映射
    modelBuilder.Entity<Book>().Ignore(b => b.IsSellFast);

     7、非空属性及错误提示信息

    Data Annotations 方式:[Required]  OR [Required(ErrorMessage = "xxx")] 

    [Required]
    public string BookName { get; set; }
    
    [Required(ErrorMessage = "请输入价格")]
    public decimal Price { get; set; }

     Flunt API 方式: 

    modelBuilder.Entity<Book>().Property(b => b.BookName).IsRequired();

     8、长度:

    Data Annotations 方式:[StringLength] 表示长度;[MinLength]表示最小长度;[MaxLength]表示最大长度

    [StringLength(10)]
    public string Name { get; set; }
    [MinLength(20), MaxLength(200)]
    public string Introduce { get; set; }

     Flunt API 方式 (Flunt Api 方式没有设置 MinLength 这个方法,长度及最大长度都用HasMaxLength 方式)

    modelBuilder.Entity<Author>().Property(a => a.Name).HasMaxLength(10);

     9、配置类型:

    Data Annotations 方式:[Column(TypeName="")]

    [Column(TypeName = "image")]
    public byte[] Photo { get; set; }

     Flunt API 方式 :

    modelBuilder.Entity<Book>().Property(b => b.Price).HasColumnType("image");

     10、防止并发:

    (1)对表做并发处理:

     Data Annotations 方式:[Timestamp]

    注意:如果要对某一个表做并发处理,就在该表中加一条Timestamp类型的字段,但是这个字段必须为byte[]类型,并且一个类中只能存在一个。

    [Timestamp]
    public byte[] RowVersion { get; set; }

     Flunt API 方式 : 

    modelBuilder.Entity<Book>().Property(b => b.RowVersion).IsRowVersion();

     (2)对某个字段作并发控制:

    Data Annotations 方式:[ConcurrencyCheck]

    [ConcurrencyCheck]
    public string BookName { get; set; }

      Flunt API 方式 :

    modelBuilder.Entity<Book>().Property(b => b.BookName).IsConcurrencyToken();

    关于 并发控制 后面的文章要详细的学习

     10、复杂类型

    Data Annotations 方式:[ComplexType]

    [ComplexType]
    public class Address
    {
      public int AddressId { get; set; }
      public string StreetAddress { get; set; }
      public string City { get; set; }
      public string State { get; set; }
      public string ZipCode { get; set; }
    }

     Flunt API 方式 : 

    modelBuilder.ComplexType<Address>();

     关于 复杂类型 后面的文章要详细的学习

    这里只列举和记录了 10 种配置方式,具体参见: http://msdn.microsoft.com/zh-cn/library/system.componentmodel.dataannotations.aspx

    下面把先前的例子的某些配置整理一下:

    Data Annotations 方式:

        //设置Author 类 映射表名为 T_Author,架构名为 Lx
        [Table("T_Author",Schema="Lx")]
        public class Author
        {       
            [Column("AuthorId",TypeName="int")]
            public int AuthorId { get; set; }
    
            //修改Name属性 映射为 AuthorName
            //长度 10
            [Column("AuthorName",TypeName="nvarchar")]
            [Required,StringLength(10)]
            public string Name { get; set; }
                    
            //设置Birthday 可空
            public DateTime? Birthday { get; set; }
    
            //设置 Photo 属性 映射类型 为 image
            [Column(TypeName = "image")]
            public byte[] Photo { get; set; }
    
            //设置 Introduce 属性最小长度 20,最大长度 100
            [MinLength(20),MaxLength(100)]
            public string Introduce { get; set; }
    
            public List<Book> MyBooks { get; set; }
        }
    
        //设置 Book 类 映射表名为 T_Books,架构名为 Lx
        [Table("T_Books", Schema = "Lx")]
        public class Book
        {
            // BookId 为主键且自增
            [Key]
            public int BookId { get; set; }
            
            public int AuthorId { get; set; }
            
            //设置 BookName 属性 不能为空,字段长度为 50
            [Required,StringLength(50)]
            public string BookName { get; set; }
            
            //DataAnnotation 方式不能控制deciaml 的精度
            //默认为(18,2)
            public decimal Price { get; set; }
    
            public bool IsSellFast { get; set; }
    
            //设置外键为 AuthorId
            [ForeignKey("AuthorId")]
            public Author Author { get; set; }
        }

      Flunt API 方式 :

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    
       //设置 Author 表名 T_Author 架构名 Lx
       modelBuilder.Entity<Author>().ToTable("T_Authors", "Lx");
    
       //设置 Name 属性 非空,映射为列名 AuthorName,长度 10
       modelBuilder.Entity<Author>().Property(a => a.Name).IsRequired()
                                     .HasColumnName("AuthorName")
                                     .HasMaxLength(10);
    
       //设置 photo 属性 映射类型为 image
       modelBuilder.Entity<Author>().Property(a => a.Photo).HasColumnType("image");
    
       //Flunt Api 无法设置最小长度
       modelBuilder.Entity<Author>().Property(a => a.Introduce).HasMaxLength(100);
    
    
       //设置 Book 表名 T_Books 架构名 Lx
       modelBuilder.Entity<Book>().ToTable("T_Books", "Lx");
    
       //设置 BookId 为主键且自动增长
       modelBuilder.Entity<Book>().HasKey(b => b.BookId)
                                           .Property(b => b.BookId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    
       //设置 AuthorId 为外键
       modelBuilder.Entity<Book>().HasRequired(b => b.Author).WithMany(a => a.MyBooks).HasForeignKey(b => b.AuthorId);
    
    //设置 BookName 属性不能为空,字符串长度 50 modelBuilder.Entity<Book>().Property(b => b.BookName).IsRequired() .HasMaxLength(50); //FluntAPI 可以设置 decimal 类型的精度 modelBuilder.Entity<Book>().Property(b => b.Price).HasColumnType("decimal").HasPrecision(3, 1);
    }

     运行程序,结果如下图:

    --=源码下载=--

    作者:Rising Sun
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    html5结构标签
    video标签、audio标签
    a标签、img图片、iframe、表单元素、div
    pre,html转义,abbr缩写,表格table
    html 列表标签
    p,br,hn,b,i,u,s,sup,sub标签
    网站开发准备学习
    交互原型设计工具
    为什么要重写hashCode()方法和equals()方法及如何重写
    Java接口回调
  • 原文地址:https://www.cnblogs.com/lxblog/p/3080881.html
Copyright © 2011-2022 走看看