代码改变世界

ADO.NET Entity Framework -Code Fisrt (二)

2012-12-27 15:41  Spring.Guo  阅读(700)  评论(0编辑  收藏  举报

Code First 可以自动根据Model 映射来创建数据库,这点非常方便。 但是按照上一节的方式创建的表,会发现,所有字符串列都是nvarchar(max),就是说每个model的属性映射的表列都是采用CodeFist 默认的设置进行创建。 这当然不科学,CodeFirst 提供了数据注释(Data Annotation) 的方式来标记每个模型的属性与表之间的映射。

  1. Convention for key : 主键映射
  2. Convention for string properties  :字符串属性映射
  3. Convention for Byte Array  : 字节数据映射
  4. Convention for Booleans :  布尔类型映射
  5. Convention for One-to-Many ReleationShips : 一对多映射
    Convention for key [Key] 标记为主键,默认是把类名+ID 的属性标记为主键
    Convention for string properties [maxLength(N)]
    [minLength(N)]

    [Required]
    字符最大长度,映射到数据库
    字符最小长度,CodeFirst 中检查,不映射到数据库
    必填
    (字符串都映射为nvarchar(n),默认设置长度映射为n=max)
    Convention for Byte Array Column(TypeName="Image") 把字节型数据映射为Image 类型,默认映射为varbinary(max)
    Convention for Booleans   sqlserver映射为bit 类型
    Convention for One-to-Many ReleationShips   外键关系,映射为 表名_主键列

1 修改Custom 的模型代码: 添加using System.ComponentModel.DataAnnotations; 引用

using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
namespace QuickStart.Model
{
   // [Table("Customer")]//存储表名Customer,默认是类名
   public class Customer
    {
       public Customer() {
           this.Orders = new List<Order>();
       }

       [MaxLength(50)]
       public string CustomerID { get; set; }
       [Required] //必填
       [MaxLength(50)] //最大长度50个汉字
       public string Name { get; set; }
       public decimal Balance { get; set; }

       /// <summary>
       /// 客户与订单是one or many
       /// </summary>
       public List<Order> Orders { get; set; }
    }
}

 

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace QuickStart.Model
{
   public class Order
    {
       public Order() {
           this.CreateTime = DateTime.Now;
           this.OrderItems = new List<OrderItem>();
       }

       public int OrderID { get; set; }
       [MaxLength(50)]
       public string Title { get; set; }
       public decimal Total { get; set; }
       public DateTime CreateTime { get; set; }

       //one or many
       public List<OrderItem> OrderItems { get; set; }
       // one or one
       public Customer Customer { get; set; }
    }
}

 

当模型被修改后,此时如果直接运行代码,Code First 会抛出一个异常,说 要创建的OrderBD 已经存在。 默认配置下CodeFisrt 是不会自动修改的。

所以,需要添加一个初始化配置,在main函数代码开始的时候,让Code First 去检测Model 是否发生更改,如果更改,就删掉原数据库,然后重新创建一个新的数据库。 此种方式更新数据库,必须要保证数据库在其他地方为被使用,否则删除数据库时将不会成功。

1  确保配置文件中,链接字符串包含保存密码配置 Persist Security Info=true

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="OrderDB" providerName="System.Data.SqlClient"
         connectionString="server=.;uid=sa;pwd=123456;database=OrderDB;Persist Security Info=true"/>
    <!--要CodeFirst能自动维护model的更改,必须添加Persist Security Info=true 项,表示保持账号密码-->
  </connectionStrings>
</configuration>

2  在main 函数中添加 using System.Data.Entity; 引用。 (此处代码与第一小节有点变化,更改过了,不过应该可以看懂)。粗体代码为修改部分

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QuickStart.Model;
using System.Data.Entity;
namespace QuickStart
{
    class Program
    {
        static void Main(string[] args)
        {
            //数据库变动初始化方法一:每次检查数据库上下文,如果模型Model发生变化,就删除现有数据库,重新创建
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<DBContextAPI>());

            CreateCustomer(); //创建顾客
            Console.ReadKey();
        }

        private static void CreateCustomer()
        {
            using (var db = new DBContextAPI())
            {
                var customer = new Customer()
                {
                    CustomerID = "20121224001",
                    Name = "张三",
                    Balance = 1000
                };
                db.Customers.Add(customer);
                int result = db.SaveChanges();
                Console.WriteLine("追加{0}条记录成功!", result);
            }
        }
    }
}

3  执行,成功后,表结构发生变化。

image