zoukankan      html  css  js  c++  java
  • Entity Framework实现属性映射约定

     Entity Framework Code First属性映射约定中“约定”一词,在原文版中为“Convention”,翻译成约定或许有些不好理解,这也是网上比较大多数的翻译,我们就当这是Entity Framework的一些使用“规则”,这样或许更好理解一些。

      Entity Framework Code First与数据表之间的映射方式有两种实现:Data Annotation和Fluent API。本文中采用创建Product类为例来说明tity Framework Code First属性映射约定的具体方式。

      1、表名及所有者

      在默认约定的情况下,Entity Framework Code First创建的表名是根据类名的英语复数形式,创建的表所有者为dbo,可以通过重写约定来指定表名及表的所有者。

      1>、Data Annotation方式

      在使用Data Annotation方式进行Entity Framework Code First与数据库映射之前,需要先添加命名空间引用。

    1
    using System.ComponentModel.DataAnnotations.Schema;


      为类配置对应表名:

    1
    2
    [Table("Product")]
    public class Product

      为类配置对应表名并指定表的所有者:

    1
    2
    [Table("Product", Schema = "dbo")]
    public class Product

      2>、Fluent API方式

      Fluent API实现配置Entity Framework Code First与数据库映射关系主要是通过继承DbContext并重写其中的OnModelCreating方法来进行的。在本文中新建类文件PortalContext.cs继承DbContext。

      在继承DbContext之前,添加命名空间引用。

    1
    using System.Data.Entity;

      重写OnModelCreating方法,配置类对应于数据库中的表名:

    1
    2
    3
    4
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>().ToTable("Product");
    }

      重写OnModelCreating方法,配置类对应于数据库中的表名,并指定表的所有者:

    1
    2
    3
    4
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>().ToTable("Product""dbo");
    }


      到此处PortalContext.cs的完整代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    using System.Data.Entity;
     
    using Portal.Entities;
     
    namespace Portal
    {
        public class PortalContext : DbContext
        {
            static PortalContext()
            {
                Database.SetInitializer(new DropCreateDatabaseIfModelChanges<PortalContext>());
            }
     
            public PortalContext()
                base("name=PortalContext")
            {
            }
     
            public DbSet<Product> Products { getset; }
     
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Entity<Product>().ToTable("Product""dbo");
            }
        }
    }

    2、字段名、长度、数据类型及是否可空

      在默认约定的情况下,Entity Framework Code First创建的列名与类的属性名相同,可以根据需要进行重新指定类属性与列名之间的映射关系。

      1>、Data Annotation方式

    1
    2
    3
    4
    5
    [Column("ProductID")]
    public int ProductID { getset; }
    [MaxLength(100)]
    [Required, Column("ProductName")]
    public string ProductName { getset; }

      在使用Required特性(Attribute)设置字段不允许为空时,需要添加命名空间引用:

    1
    using System.ComponentModel.DataAnnotations;

      2>、Fluent API方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>().Property(t => t.ProductID)
            .HasColumnName("ProductID");
        modelBuilder.Entity<Product>().Property(t => t.ProductName)
            .IsRequired()
            .HasColumnName("ProductName")
         .HasMaxLength(100);
    }

    在默认情况下,int类型的属性生成的列名对应SQL SERVER列int类型;而String类型的属性则对应SQL SERVER列的NVARCHAR类型。若类的字符串类型属性未设置MaxLength,则生成对应的列类型为NVARCHAR(MAX)。

      为属性指定对应的SQL SERVER数据类型:

    1
    2
    3
    4
    5
    [Column("UnitPrice", TypeName = "MONEY")]
    public decimal UnitPrice { getset; }
    modelBuilder.Entity<Product>().Property(t => t.UnitPrice)
        .HasColumnName("UnitPrice")
        .HasColumnType("MONEY");

      到此步,Product.cs类文件的完整代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
     
    namespace Portal.Entities
    {
        [Table("Product", Schema = "dbo")]
        public class Product
        {
            [Column("ProductID")]
            public int ProductID { getset; }
     
            [MaxLength(100)]
            [Required, Column("ProductName")]
            public string ProductName { getset; }
     
            [Column("UnitPrice", TypeName = "MONEY")]
            public decimal UnitPrice { getset; }
        }
    }

    3、主键

      Entity Framework Code First的默认主键约束:属性名为[ID]或[类名 + ID]。如在Product类中,Entity Framework Code First会根据默认约定将类中名称为ID或ProductID的属性设置为主键。Entity Framework Code First主键的默认约定也一样可以进行重写,重新根据需要进行设置。

      1>、Data Annotation方式

    1
    2
    3
    [Key]
    [Column("ProductID")]
    public int ProductID { getset; }

      2>、Fluent API方式

    1
    2
    3
    4
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>().HasKey(t => t.ProductID);
    }

      若一个表有多个主键时:

    1
    2
    3
    4
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>().HasKey(t => new { t.KeyID, t.CandidateID });
    }

      4、数据库自动生成字段值

      Entity Framework Code First对于int类型的主键,会自动的设置其为自动增长列。但有时我们确实不需是自动增长的,可以通过以下方式进行取消自动增长。

      1>、Data Annotation方式

    1
    2
    3
    4
    [Key]
    [Column("ProductID")]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int ProductID { getset; }

      2>、Fluent API方式

    1
    2
    3
    4
    5
    6
    7
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>().HasKey(t => t.ProductID);
        modelBuilder.Entity<Product>().Property(t => t.ProductID)
            .HasColumnName("ProductID")
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    }

    5、数字类型长度及精度

      在Product类中,UnitPrice表示单价,对于价格类的字段,我们通常会希望其保留2为小数。这时可以使用Fluent API进行设置,且Data Annotation不支持该设置。

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>().Property(t => t.UnitPrice)
            .HasColumnName("UnitPrice")
            .HasPrecision(18, 2);
    }

      6、非数据库字段属性

      在类中,如果有一些属性不需要映射到对应生成的数据表中,可以通过以下方式设置。

      1>、Data Annotation方式

    [NotMapped]
    public string Remark { get; set; }

      2>、Fluent API方式

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>().Ignore(t => t.Remark);
    }

       7、Fluent API配置Configuration映射类

      在使用Fluent API进行Entity Framework Code First数据库映射时,除了以上的在重写OnModelCreating方法中直接对Entity进行配置之外,也可以对Configurations进行配置。这时可以先写一个单独的类,将数据表的全部映射要求都写在构造函数中。

      ProductMap.cs类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.ModelConfiguration;
     
    using Portal.Entities;
     
    namespace Portal.Mapping
    {
        public class ProductMap : EntityTypeConfiguration<Product>
        {
            public ProductMap()
            {
                // Primary Key
                this.HasKey(t => t.ProductID);
     
                // Properties
                this.Property(t => t.ProductID)
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
                this.Property(t => t.ProductName)
                    .IsRequired()
                    .HasMaxLength(100);
     
                // Table & Column Mappings
                this.ToTable("Product");
                this.Property(t => t.ProductID).HasColumnName("ProductID");
                this.Property(t => t.ProductName).HasColumnName("ProductName");
                this.Property(t => t.UnitPrice)
                    .HasColumnName("UnitPrice")
                    .HasPrecision(18, 2);
            }
        }
    }

    有了上面的映射类之后,在重写OnModelCreating方法中则可以直接调用映射类,从而减少了OnModelCreating方法的复杂度,同时也增强了代码维护的可读性。

    1
    2
    3
    4
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new ProductMap());
    }

     

  • 相关阅读:
    Postman使用教程
    CAD和ArcGIS转换 矢量配准
    SAP CRM Advanced search和Simple search里Max hit表现行为的差异
    SAP CRM Product simple search的启用步骤
    如何快速定位SAP CRM订单应用(Order Application)错误消息抛出的准确位置
    如何动态修改SAP CRM WebClient UI表格栏的宽度
    如何在SAP CRM WebClient UI里创建web service并使用ABAP消费
    如何处理SAP CRM Web Service错误
    如何使用SAP CRM WebClient UI实现一个类似新浪微博的字数统计器
    如何开启SAP CRM基于WORD模板创建附件的功能
  • 原文地址:https://www.cnblogs.com/lpbca/p/7147109.html
Copyright © 2011-2022 走看看