[转]EF 4.1 Code First
这篇文章介绍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 ProductPlaced 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 relationshipInverseProperty:用于定义多重外键关系约束。我们在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的更多相关文章
- 使用 EF Power Tool Code Frist 生成 Mysql 实体
原文:使用 EF Power Tool Code Frist 生成 Mysql 实体 1,在要生成的项目上右键 2, 3, 4, 5, 生成后的效果 已知问题: 1,在Mys ...
- 基于EF Core的Code First模式的DotNetCore快速开发框架
前言 最近接了几个小单子,因为是小单子,项目规模都比较小,业务相对来说,也比较简单.所以在选择架构的时候,考虑到效率方面的因素,就采取了asp.net+entity framework中的code f ...
- 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持
前言 距离上一篇文章<基于EF Core的Code First模式的DotNetCore快速开发框架>已过去大半个年头,时光荏苒,岁月如梭...比较尴尬的是,在这大半个年头里,除了日常带娃 ...
- 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,这种形 ...
- EF Core 的 Code First 模式
0 前言 本文正文第一节,会对 Code First 进行基本的介绍,以及对相关名词进行说明,读者一开始可以不用在这里消耗过多时间,可以先操作一遍例子,再回过头理解. 第二节,以一个简单的例子,展示 ...
- ORM系列之二:EF(2)Code First
目录 1. Code First是什么? 2. Code First 简单示例 3. 数据存储 4. 迁移 Code First是什么 Code First 顾名思义就是先写代码,当然不是乱写,而是按 ...
- EF中的Code First
一些概念 POCO POCO(Plain Old CLR Object)的概念是从java的POJO借用而来,而两者的含义是一致的,不同的仅仅是使用的语言不一样.所以POCO的解释就是“Plai ...
- EF 下的code fist 模式编程
EF 分两种模式 codefirst(就是不知道数据是啥,也没有数据库) 和 database fist (数据已经设计好了) 首先打开vs 新建一个项目 创建一个控制台程序 然后 新建一个Tea ...
- EF Core学习Code First
下面通过实例来学习EF Core Code First,也就是通过EF Core迁移来完成从模型生成数据库. 本实例使用EntityFrameworkCore SQLite 数据库进行介绍,大家也可以 ...
随机推荐
- spring classpath & classpath*
classpath-找到系统类路径下的第一个匹配的配置文件 classpath*-找到系统类路径下的所有符合要求的配置文件 参考资料:http://www.micmiu.com/j2ee/spring ...
- WinForm下窗体标题栏上有“帮助”按钮
将FormBorderStyle设置为Sizable. 最大化和最小化设置为false helpbutton 设置为true
- 框架模式 MVC 在Android中的使用
算来学习Android开发已有2年的历史了,在这2年的学习当中,基本掌握了Android的基础知识.越到后面的学习越感觉困难,一来是自认为android没啥可学的了(自认为的,其实还有很多知识科学), ...
- Hark的数据结构与算法练习之Bogo排序
算法说明 Bogo排序是交换排序的一种,它是一种随机排序,也是一种没有使用意义的排序,同样也是一种我觉得很好玩的排序. 举个形象的例子,你手头有一副乱序的扑克牌,然后往天上不停的扔,那么有一定机率会变 ...
- Bitnami Redmine安装和插件配置
公司要进行敏捷开发管理,最后选择Redmine作为管理工具. 而Redmine本身的安装非常麻烦,要安装mysql,ruby,redmine,apach. 显然这不是一个偷懒的人应该做的,最后找到Bi ...
- BZOJ3853 : GCD Array
1 n d v相当于给$a[x]+=v[\gcd(x,n)=d]$ \[\begin{eqnarray*}&&v[\gcd(x,n)=d]\\&=&v[\gcd(\fr ...
- storm环境搭建(前言)—— 翻译 Setting Up a Development Environment
Setting Up a Development Environment 搭建storm开发环境所需步骤: Download a Storm release , unpack it, and put ...
- HDU1853 & 蜜汁建图+KM模板
题意: 给你一个N个点M条边的带权有向图,现在要你求这样一个值:该有向图中的所有顶点正好被1个或多个不相交的有向环覆盖.这个值就是 所有这些有向环的权值和. 要求该值越小越好. SOL: 本来还想ta ...
- fireBug使用指南
据说,对于网页开发人员来说,Firebug是Firefox浏览器中最好的插件之一. 我最近就在学习怎么使用Firebug,网上找到一篇针对初学者的教程,感觉比较有用,就翻译了出来. ========= ...
- JS按位非(~)运算符与~~运算符的理解分析
按位非运算符,简单的理解就是改变运算数的符号并减去1,当然,这是只是简单的理解能转换成number类型的数据. 那么,对于typeof var!==”number”的类型来说,进行运算时,会尝试转化成 ...