这篇文章介绍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. hdu 5312 数学

  2. Struts2中ActionContext和ServletActionContext

    转自:http://blog.sina.com.cn/s/blog_6c9bac050100y9iw.html 在Web应用程序开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在A ...

  3. BZOJ1580 : [Usaco2009 Hol]Cattle Bruisers 杀手游戏

    以贝茜为参照物,则贝茜固定于原点,每个杀手是一个圆心在某条射线上的圆. 解出每个杀手可以射杀贝茜的时间区间,然后扫描线即可,时间复杂度$O(n\log n)$. #include<cstdio& ...

  4. C#中DataTable使用技巧

    在项目中经常用到DataTable,如果DataTable使用得当,不仅能使程序简洁实用,而且能够提高性能,达到事半功倍的效果,现对DataTable的使用技巧进行一下总结. 一.DataTable简 ...

  5. Struts2之自定义类型转换器

    Struts2自定义类型转换器分为局部类型转换器和全局类型转换器 (1)局部类型转换器 如果页面传来一个参数reg.action?birthday=2010-11-12到后台action,然后属性用d ...

  6. Java 利用Apache Commons Net 实现 FTP文件上传下载

    package woxingwosu; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import ...

  7. C++ Ouput Exactly 2 Digits After Decimal Point 小数点后保留三位数字

    在C++编程中,有时候要求我们把数据保留小数点后几位,或是保留多少位有效数字等等,那么就要用到setiosflags和setprecision函数,记得要包含头文件#include <ioman ...

  8. StereoBM::disp12MaxDiff Crash the Release

    Initializing "cv::StereoBM bm.state->disp12MaxDiff" should be careful, inappropriate va ...

  9. SQL Server 中的触发器(trigger)

    SQL Server 触发器 触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程.触发器主要是通过事件进行触发被自动调用执行的.而存储过程可以通过存储过程的名称被调用. Ø 什么是触发器 ...

  10. 一、saltstack简介和安装

    系统环境:CentOS6.5 准备yum源: epel源(包含了saltstack的包).阿里源(CentOS-Base.repo) Host解析文件: # cat /etc/hosts 192.16 ...