zoukankan      html  css  js  c++  java
  • Entity Framework 4.1 之二 : 覆盖默认的约定

    原文名称:Entity Framework 4.1: Override conventions (2)
     
    在这篇文章中,我将讨论如何覆盖默认的约定。
    我们已经看过了在 EF4.1 Code First 中模型与数据库中的默认约定。当这些约定不能满足我们的时候,我们有两种不同的途径来覆盖这些约定:
    • 拦截模型的构建器,使用流畅的 API 来修改模型
    • 为我们的模型增加标签
    在未来的版本中,我们还将有能力增加或者删除约定,现在还没有提供这个能力。
    对于我们基本的例子,我们使用下面所示的订单类。
    public class Order
    {
    public int OrderID { get; set; }
    public string OrderTitle { get; set; }
    public string CustomerName { get; set; }
    public DateTime TransactionDate { get; set; }
    }

    构建器

    我们从模型的构建器开始吧。为了使用模型构建器,我们必须重写 DbContext 的一个方法 OnModelCreating.
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    base.OnModelCreating(modelBuilder);
    // Map schemas
    modelBuilder.Entity<Order>().ToTable("efdemo.Order");
    }
    默认情况下,EF 将实体映射到数据库中 dbo 架构下的同名表上,这里我将订单映射到数据库中 efdemo 架构下的 Order 表。
    模型构建器提供了一种流畅的 API 方式,由于方法返回同样的对象,意味着可以使用链式的方法将操作连接在一起。下面是另外一个例子。
    modelBuilder.Entity<Order>().Property(x => x.OrderID)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
    .IsRequired()
    .HasColumnName(
    "TheOrderID");
     在这里,我们对属性 OrderID 做了三件事:
    • 标识它是标识列,自增长的列
    • 必须的列,非空
    • 映射到数据库中的 TheOrderID
    这里,我们将涉及 EF4.1 的强大的功能:通过 Lambda 表达式,可以逐条定义属性,而不是使用字符串来标识属性,这有以下的优势:
    • 有智能提示
    • 有编译时的错误检查
    • 属性的类型是已知的,你可以在之后定义,例如,只有字符串可以有最大或最小长度。
    那么,通常我们重写什么约定呢?看一下 Order 类,下面的情况不太符合默认约定:
    • 表必须属于 dbo Schema
    • OrderID 是主键,但不是自增长的类型
    • 所有其他列是非空的
    • 字符串列的长度是 128
     我们可以通过模型构建器重写这些约定:
    // Map schemas
    modelBuilder.Entity<Order>().ToTable("efdemo.Order");
    // Identity Column
    modelBuilder.Entity<Order>().Property(x => x.OrderID)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    // String columns
    modelBuilder.Entity<Order>().Property(x => x.OrderTitle)
    .IsRequired()
    .HasMaxLength(
    64);
    modelBuilder.Entity
    <Order>().Property(x => x.CustomerName)
    .IsRequired()
    .HasMaxLength(
    32);
    // Date Columns
    modelBuilder.Entity<Order>().Property(x => x.TransactionDate)
    .IsRequired();
     看起来有点冗长,但是不用修改模型,纯粹的 POCO.

    使用标注

    现在,我们在看一下另外一种方式,使用标签。
    这种方式的代码要少得多,感觉更加自然,通过标签来说明属性。唯一的问题是你的类不再 POCO,虽然使用的类并没有来自 EF,而是 System.ComponentModel.DataAnnotations , .NET 的验证模块。看一下例子吧。
    public class Order
    {
    public int OrderID { get; set; }

    [Required]
    [StringLength(
    32, MinimumLength = 2)]
    public string OrderTitle { get; set; }

    [Required]
    [StringLength(
    64, MinimumLength = 5)]
    public string CustomerName { get; set; }

    [Required]
    public DateTime TransactionDate { get; set; }
    }
    这里我们告诉模型构建器将 OrderTitle 映射到非空的长度为32 的 nvarchar 列,最小长度为 2没有映射到架构中,但是将被用来验证。
    这个例子我给出了一些业务标注,也可以加上一些技术标注。
    public class Order
    {
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int OrderNumber { get; set; }

    }
    这里我们强制 OrderNumber 属性作为主键,而且是一个自增长的列。
    还可以使用 OnModelCreated 或者其他的标签来覆盖约定,有一些限制需要注意,例如(这是我注意到的):
    • 表名不支持使用标签进行标注
    • 最小长度在 OnModelCreated 中不支持
    • 正则表达式在 OnModelCreated 中不支持
    着比较好理解,OnModelCreated 属于表映射,(正则或者最小长度不能在数据库中表示),标注支持常见的验证。
    我的原则:
    • 使用标注来丰富模型的验证规则
    • 使用 OnModelCreated 来完成数据库的约束(主键,自增长,表名,列类型等等)
    这些方式可以使你的模型更加丰富而且保持 POCO,你可以到处重用你的模型,还能从验证规则中获得好处。
  • 相关阅读:
    my15_ mysql binlog格式从mixed修改为row格式
    my14_mysql指定时间恢复之模拟从库
    my13_mysql xtrabackup备份的时间点
    必知必会的图论算法
    leetcde37. Sudoku Solver
    leetcode36. Valid Sudoku
    leetcode52. N-Queens II
    leetcode51. N-Queens
    First Missing Positive
    Maximum Gap
  • 原文地址:https://www.cnblogs.com/haogj/p/2039149.html
Copyright © 2011-2022 走看看