这篇文章介绍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. linux下验证码无法显示:Could not initialize class sun.awt.X1 解决方案

    转自:http://my.oschina.net/xiangtao/blog/28441 网站验证码突然无法显示,并报如下错误. Caused by: java.lang.NoClassDefFoun ...

  2. 关于服务器响应,浏览器请求的理解以及javaWeb项目的编码问题

    1.服务器(Server)响应,浏览器(Brower)请求: 对于B/S的软件,数据的传递体现在,用户利用浏览器请求,以获得服务器响应.在JavaWeb项目中,大致包含.java文件的数据处理模块,和 ...

  3. 修改ViewPager调用setCurrentItem时,滑屏的速度

    原文摘自: 修改ViewPager调用setCurrentItem时,滑屏的速度 在使用ViewPager的过程中,有需要直接跳转到某一个页面的情况,这个时候就需要用到ViewPager的setCur ...

  4. loj 1156(二分+最大流)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26870 思路:由于溢出问题,wa了半天,还以为构图错了呢,查了半天 ...

  5. Hadoop开发中,如何开启、关闭控制台打印调试信息

    第一种方法: 修改$HADOOP_CONF_DIR/log4j.properties文件 hadoop.root.logger=ALL,console 第二种方法 开启:export HADOOP_R ...

  6. jq生成目录文件树jQuery Ztree基本用法

    转自:http://www.cnblogs.com/linjiqin/p/4547452.html 1.首先在页面上有<ul/>标签 ? 1 <ul id="tree&qu ...

  7. Hark的数据结构与算法练习之梳排序

    算法说明梳排序是交换排序的一种,它其实也是改自冒泡排序,不同之处是冒泡排序的比较步长恒定为1,而梳排序的比较步长是变化的. 步长需要循环以数组长度除以1.3,到最后大于等于1即可. 光说可能比较抽象, ...

  8. ember.js:使用笔记10 常用方法

    init: controller中初始化方法,                               //注意该方法是在其他方法之前,所以取不出this,model等值: 跳转:this.tra ...

  9. ZOJ3795 Grouping(强连通分量+缩点+记忆化搜索)

    题目给一张有向图,要把点分组,问最少要几个组使得同组内的任意两点不连通. 首先考虑找出强连通分量缩点后形成DAG,强连通分量内的点肯定各自一组,两个强连通分量的拓扑序能确定的也得各自一组. 能在同一组 ...

  10. BZOJ3570 : DZY Loves Physics I

    考虑两个质量均为m,速度分别v1.v2的小球发生完全弹性碰撞的影响: 由动能守恒得: $\frac{1}{2}mv_1^2+\frac{1}{2}mv_2^2=\frac{1}{2}mv_1'^2+\ ...