Entity Framework 4.1 之二 : 覆盖默认的约定

在这篇文章中,我将讨论如何覆盖默认的约定。
我们已经看过了在 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,你可以到处重用你的模型,还能从验证规则中获得好处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值