这篇文章介绍Code First开发以及如何与DbContext API一起使用。Code First允许使用C#或VB.NET类定义模型,在类或属性上有选择性的执行额外的配置或者使用Fluent API。模型可用于生成数据库架构或映射现有的数据库。

本次演示需要安装Visual Studio 2010。

映射现有数据库

本次演示将展示Code First生成数据库架构,但同样适用于映射现有数据库。如果Code First指向一个没有创建的现有数据库,那么它会尝试使用指定的配置访问数据库。将Code First指向现有数据库最简单的方法是添加一个App/Web.config连接字符串,和你派生的DbContext类同名:

  <connectionStrings>
<add name="MyProductContext"
providerName="System.Data.SqlClient"
connectionString="Server=.\SQLEXPRESS;Database=Products;Trusted_Connection=true;"/>
</connectionStrings>

1、安装 EF 4.1

可以到这里下载 Entity Framework 4.1

2、创建一个新的应用程序

为了使问题简单,我们建立一个基本的控制台应用程序,使用Code First执行数据访问:

1. 打开Visual Studio 2010

2. File -> New -> Project…

3. 从左侧菜单中选择"Windows",然后选择"Console Application"

4. 输入"CodeFirstSample"作为名字

5. 选择"OK"

3、创建模型

让我们使用类定义一个非常简单的模型。我只在Program文件中定义它们,但是在真正的应用程序中,应该拆分类到单独的文件中或者单独的项目中。

在Program类下面定义以下两个类:

public class Category
{
public string CategoryId { get; set; }
public string Name { get; set; } public virtual ICollection<Product> Products { get; set; }
} public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public string CategoryId { get; set; } public virtual Category Category { get; set; }
}

4、创建Context

使用类进行数据访问最简单的方式是在我的模型中定义一个继承自System.Data.Entity.DbContext的上下文以及为每个类公开一个类型化的DbSet<TEntity>。

现在我们开始使用Entity Framework的类型,所以需要添加EntityFramework NuGet包:

1. Project –> Add Library Package Reference…

2. 选择"Onlie"选项卡

3. 搜索"EntityFramework"并选择该包

4. 点击"Install"

在Program.cs的顶部添加一个using语句:

using System.Data.Entity;

在现有类的下面添加一个继承自DbContext的上下文:

public class ProductContext : DbContext
{
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}

 5、读写数据

代码在Program文件中的Main方法中,如下:

class Program
{
static void Main(string[] args)
{
using (var db = new ProductContext())
{
// Add a food category
var food = new Category { CategoryId = "FOOD", Name = "Foods" };
db.Categories.Add(food);
int recordsAffected = db.SaveChanges(); Console.WriteLine(
"Saved {0} entities to the database, press any key to exit.",
recordsAffected); Console.ReadKey();
}
}
}

我的数据在哪里?

如果不添加上面的App.config,根据约定DbContext已经localhost\SQLEXPRESS上创建了一个数据库。数据库根据你的派生上下文的完全限定名命名,在我们的例子中是"CodeFirstSample.ProductContext"。添加了App.config,那么就根据配置生成数据库了。

模型发现

DbContext通过查看DbSet属性可以知道什么类包含在模型中。然后它使用默认的Code First约定寻找主键、外键等等。

6、读写更多的数据

让我们展示更多的功能。我们在DbSet上使用Find方法,根据主键来查找实体。如果没找到匹配的实体,Find就返回null。我们还可以使用LINQ查询Food类别下的所有产品,根据字母顺序排序。

修改上面Main方法的代码:

class Program
{
static void Main(string[] args)
{
using (var db = new ProductContext())
{
// Use Find to locate the Food category
var food = db.Categories.Find("FOOD");
if (food == null)
{
food = new Category { CategoryId = "FOOD", Name = "Foods" };
db.Categories.Add(food);
} // Create a new Food product
Console.Write("Please enter a name for a new food: ");
var productName = Console.ReadLine(); var product = new Product { Name = productName, Category = food };
db.Products.Add(product); int recordsAffected = db.SaveChanges(); Console.WriteLine(
"Saved {0} entities to the database.",
recordsAffected); // Query for all Food products using LINQ
var allFoods = from p in db.Products
where p.CategoryId == "FOOD"
orderby p.Name
select p; Console.WriteLine("All foods in database:");
foreach (var item in allFoods)
{
Console.WriteLine(" - {0}", item.Name);
} Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
}

7、设置初始化策略

在下面的部分,将开始改变我们的模型,从而意味着数据库架构也需要改变。目前,还没有"out of box"的解决方案可以迁移现有架构。数据库迁移是我们目前正在处理的事情,在这方面Code First Migratioins Alpha3已经可用了。

虽然没有RTM的迁移方案,但是当上下文在应用程序域中第一次使用时有机会运行一些自定义的逻辑来初始化数据库。如果你想为了测试插入一些种子数据非常方便,同时如果模型发生了变化重新生成数据库也非常有用。在EF中包含几个初始化策略,当然你也可以自定义你自己的策略。

本演示仅仅想模型发生变化时,移除并重新创建数据库,所以在Main方法的顶部添加如下代码:

Database.SetInitializer<ProductContext>(
new DropCreateDatabaseIfModelChanges<ProductContext>());

8、数据批注

目前为止,我们仅仅让EF使用默认的约定发现模型,但是有些时候我们的类不遵循约定,我们需要执行进一步的配置。有两个选项,这一部分看一下数据批注,然后下一部分是Fluent API。

在我们的模型中添加一个supplier类:

public class Supplier
{
public string SupplierCode { get; set; }
public string Name { get; set; }
}

还需要添加一个集合到派生的上下文:

public class ProductContext : DbContext
{
public ProductContext()
{ } public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Supplier> Suppliers { get; set; }
}

如果现在运行我们的程序会得到一个InvalidOperationException异常,说是"EntityType 'Supplier' has no key defined. Define the key for this EntityType."因为EF没办法知道SupplierCode是Supplier的主键。

现在我们使用数据批注,所以需要在Program.cs的顶部添加一个using语句:

using System.ComponentModel.DataAnnotations;

现在我们就可以为SupplierCode属性添加批注指定它为主键:

public class Supplier
{
[Key]
public string SupplierCode { get; set; }
public string Name { get; set; }
}

EF支持的批注:

详细的说明可参阅:http://msdn.microsoft.com/zh-cn/library/gg193958.aspx

    • KeyAttribute

              [Key]
      public int CategoryId { get; set; }
    • StringLengthAttribute
    •         [StringLength(, ErrorMessage = "Description Max Length is 100")]
      public string Name { get; set; }
    • MaxLengthAttribute
              [MaxLength(), MinLength()]
      public string Name { get; set; }
    • ConcurrencyCheckAttribute
    • RequiredAttribute
    • TimestampAttribute
    • ComplexTypeAttribute
    • ColumnAttribute 
              [Column("demo_id")]
      public int CategoryId { get; set; }

      Placed on a property to specify the column name, ordinal & data type

    • TableAttribute 
          [Table("Products")]
      public class Product

      Placed on a class to specify the table name and schema

    • InversePropertyAttribute 
      Placed on a navigation property to specify the property that represents the other end of a relationship
      InverseProperty:用于定义多重外键关系约束。我们在EF中通过导航属性定义主外键关系
    • ForeignKeyAttribute 
      Placed on a navigation property to specify the property that represents the foreign key of the relationship
    • DatabaseGeneratedAttribute 
      Placed on a property to specify how the database generates a value for the property (Identity, Computed or None)
      DatabaseGenerated,它后有三个枚举值:Identity、None和Computed。
      Identity:自增长
      None:不处理
      Computed:表示这一列是计算列。
    • NotMappedAttribute 
      Placed on a property or class to exclude it from the database
              [NotMapped]
      public string temp
      {
      get
      {
      return String.Format("Name:{0} Category:{1}", Name, Category.Name);
      }
      }

9、Fluent API

Fluent API被认为是更高级的功能,我们推荐使用数据批注,除非你的需求要求你使用Fluent API。

访问fluent API,我们重写DbContext中的OnModelCreating方法,下面的代码中,我们使用fluentAPI配置Supplier的Name属性为必须:

public class ProductContext : DbContext
{
public ProductContext()
{ } public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Supplier> Suppliers { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Supplier>()
.Property(s => s.Name)
.IsRequired();
}
}

原文地址: http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-code-first-walkthrough.aspx

[转]EF 4.1 Code First的更多相关文章

  1. 使用 EF Power Tool Code Frist 生成 Mysql 实体

    原文:使用 EF Power Tool Code Frist 生成 Mysql 实体 1,在要生成的项目上右键   2,   3,   4,   5,  生成后的效果     已知问题: 1,在Mys ...

  2. 基于EF Core的Code First模式的DotNetCore快速开发框架

    前言 最近接了几个小单子,因为是小单子,项目规模都比较小,业务相对来说,也比较简单.所以在选择架构的时候,考虑到效率方面的因素,就采取了asp.net+entity framework中的code f ...

  3. 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持

    前言 距离上一篇文章<基于EF Core的Code First模式的DotNetCore快速开发框架>已过去大半个年头,时光荏苒,岁月如梭...比较尴尬的是,在这大半个年头里,除了日常带娃 ...

  4. C# 嵌入dll 动软代码生成器基础使用 系统缓存全解析 .NET开发中的事务处理大比拼 C#之数据类型学习 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持 基于EF Core的Code First模式的DotNetCore快速开发框架 【懒人有道】在asp.net core中实现程序集注入

    C# 嵌入dll   在很多时候我们在生成C#exe文件时,如果在工程里调用了dll文件时,那么如果不加以处理的话在生成的exe文件运行时需要连同这个dll一起转移,相比于一个单独干净的exe,这种形 ...

  5. EF Core 的 Code First 模式

    0 前言 本文正文第一节,会对 Code First 进行基本的介绍,以及对相关名词进行说明,读者一开始可以不用在这里消耗过多时间,可以先操作一遍例子,再回过头理解. 第二节,以一个简单的例子,展示 ...

  6. ORM系列之二:EF(2)Code First

    目录 1. Code First是什么? 2. Code First 简单示例 3. 数据存储 4. 迁移 Code First是什么 Code First 顾名思义就是先写代码,当然不是乱写,而是按 ...

  7. EF中的Code First

     一些概念 Ÿ POCO POCO(Plain Old CLR Object)的概念是从java的POJO借用而来,而两者的含义是一致的,不同的仅仅是使用的语言不一样.所以POCO的解释就是“Plai ...

  8. EF 下的code fist 模式编程

    EF 分两种模式 codefirst(就是不知道数据是啥,也没有数据库)  和 database fist (数据已经设计好了) 首先打开vs  新建一个项目 创建一个控制台程序 然后 新建一个Tea ...

  9. EF Core学习Code First

    下面通过实例来学习EF Core Code First,也就是通过EF Core迁移来完成从模型生成数据库. 本实例使用EntityFrameworkCore SQLite 数据库进行介绍,大家也可以 ...

随机推荐

  1. IOS8 空项目全屏

    打开工程项目属性文件,点击Target下面的第一项,再选择General选项卡,向下找到Use Asset Catalog按钮.点击它. 弹出对话框,点击Migrate即可.这样,应用尺寸就能根据屏幕 ...

  2. poj 2378(树形dp)

    题目链接:http://poj.org/problem?id=2378 思路:num[u]表示以u为根的子树的顶点个数(包括),如果去掉u之后u的每棵子树都小于等于n/2,则选择u. #include ...

  3. CC2540开发板学习笔记(五)——串口通信

    (一)串口发送 一.实验现象: 开发板实现功能发送 二.实验过程 1.PL2303 USB转串口电路图 2.串口发送 (1)查看用户手册有: UART0 对应的外部设备 IO 引脚关系为: P0_2 ...

  4. mysql忘记root密码

    skip-grant-tables:非常有用的mysql启动参数 介绍一个非常有用的mysql启动参数—— --skip-grant-tables.顾名思义,就是在启动mysql时不启动grant-t ...

  5. IE下Checkbox标签的onchange事件兼容

    Checkbox onchange事件在谷歌上ok,在ie8上不起作用了. 一番周折,测试发现勾选了以后还要点击其他位置才会触发onchange事件. 用度娘查询了一下. 有下面两种解决方式: 用on ...

  6. 2016.6.23 PHP实现新闻发布系统主体部分

    1.新闻发布系统的列表: <html><meta http-equiv="Content-Type" content="text/html; chars ...

  7. jquery.validate.js使用说明——后台添加用户邮箱功能:非空、不能重复、格式正确

    重点内容为:  jQuery验证控件jquery.validate.js使用说明+中文API[http://www.tuicool.com/articles/iABvI3] 简单教程可以参考[jQue ...

  8. 水题 ZOJ 3875 Lunch Time

    题目传送门 /* 水题:找排序找中间的价格,若有两个,选价格大的: 写的是有点搓:) */ #include <cstdio> #include <iostream> #inc ...

  9. 【python游戏编程之旅】第一篇---初识pygame

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 一.pygame简介 Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础 ...

  10. 【BZOJ】3319: 黑白树(并查集+特殊的技巧/-树链剖分+线段树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3319 以为是模板题就复习了下hld............................. 然后n ...