CodeFirst建模:DataAnotation
示例一
新建一个控制台应用程序,并安装entityframework
新建一个文件Blog.cs类,输入以下代码:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace DataAnnotations
{
public class Blog
{
[Key]
public int PrimaryTrackingKey { get; set; } [Required]
public string Title { get; set; } [MaxLength()]
public string BloggerName { get; set; } [NotMapped]
public string BlogCode
{
get
{
return Title.Substring(, ) + ":" + BloggerName.Substring(, );
}
}
}
}
这个示例就是演示代码中的4个标记,接下来生成DbContext类:
using System.Data.Entity; namespace DataAnnotations
{
internal class TestContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
}
}
程序的执行文件Program.cs如下:
using System; namespace DataAnnotations
{
internal class Program
{
private static void Main(string[] args)
{
populate();
retreive();
Console.WriteLine("请按任意键结束!");
Console.ReadKey();
} private static void populate()
{
using (var context = new TestContext())
{
var blog = new Blog { Title = "Hello World! ", BloggerName = "You are freshman." };
context.Blogs.Add(blog);
context.SaveChanges();
}
}//void private static void retreive()
{
using (var context = new TestContext())
{
foreach (var blog in context.Blogs)
{
Console.WriteLine("{0}.Title = {1}, BloggerName = {2}", blog.PrimaryTrackingKey, blog.Title, blog.BloggerName);
}
}
}//void
}
}
执行程序,并按任意键终止!
可以在其生成的数据库中找到Blogs表,表的创建代码如下:
CREATE TABLE [dbo].[Blogs] (
[PrimaryTrackingKey] INT IDENTITY (1, 1) NOT NULL,
[Title] NVARCHAR (MAX) NOT NULL,
[BloggerName] NVARCHAR (50) NULL,
CONSTRAINT [PK_dbo.Blogs] PRIMARY KEY CLUSTERED ([PrimaryTrackingKey] ASC)
);
此代码和Blog.cs代码对照,可以知道每个标记的含义。[Key]是PRIMARY KEY,[Required]是NOT NULL,[MaxLength(50)]中的数字对应NVARCHAR(50)中的数字,[NotMapped]表示这个属性不用保存在数据库中。
这里要说明的是,整数类型的主键默认identity(1,1), string类型默认映射为nvarchar(max)。
示例二
这个示例演示复合主键与复合外键:
模型文件为:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace DataAnnotations
{
public class Passport
{
[Key]
[Column(Order = )]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int PassportNumber { get; set; } [Key]
[Column(Order = )]
public string IssuingCountry { get; set; } public DateTime Issued { get; set; }
public DateTime Expires { get; set; }
} public class PassportStamp
{
[Key]
public int StampId { get; set; } public DateTime Stamped { get; set; }
public string StampingCountry { get; set; } [ForeignKey(name: "Passport")]
[Column(Order = )]
public int PassportNumber { get; set; } [ForeignKey(name: "Passport")]
[Column(Order = )]
public string IssuingCountry { get; set; } public Passport Passport { get; set; }
}
}
生成的数据库表的代码为:
CREATE TABLE [dbo].[Passports] (
[PassportNumber] INT NOT NULL,
[IssuingCountry] NVARCHAR (128) NOT NULL,
[Issued] DATETIME NOT NULL,
[Expires] DATETIME NOT NULL,
CONSTRAINT [PK_dbo.Passports] PRIMARY KEY CLUSTERED ([PassportNumber] ASC, [IssuingCountry] ASC)
); CREATE TABLE [dbo].[PassportStamps] (
[PassportNumber] INT NOT NULL,
[IssuingCountry] NVARCHAR (128) NULL,
[StampId] INT IDENTITY (1, 1) NOT NULL,
[Stamped] DATETIME NOT NULL,
[StampingCountry] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_dbo.PassportStamps] PRIMARY KEY CLUSTERED ([StampId] ASC),
CONSTRAINT [FK_dbo.PassportStamps_dbo.Passports_PassportNumber_IssuingCountry] FOREIGN KEY ([PassportNumber], [IssuingCountry]) REFERENCES [dbo].[Passports] ([PassportNumber], [IssuingCountry])
); GO
CREATE NONCLUSTERED INDEX [IX_PassportNumber_IssuingCountry]
ON [dbo].[PassportStamps]([PassportNumber] ASC, [IssuingCountry] ASC);
复合键的Order是按着大小排序,并不是指序号。外键的顺序要与主键对应列位置一致。Order值不一定要相等。
代码中使用[DatabaseGenerated(DatabaseGeneratedOption.None)]关闭了整数类型主键的Identity特性。另外两个选项为Computed,Identity。
示例三
模型代码
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace DataAnnotations
{
public class Blog
{
public int BlogId { get; set; } [Required]
public string Title { get; set; } public BlogDetails BlogDetail { get; set; }
} [ComplexType]
public class BlogDetails
{
public DateTime? DateCreated { get; set; } [MaxLength()]
public string Description { get; set; }
}
}
没有主键,又没有引用其他实体的类为ComplexType,这里的标记是可以省略的。上下文代码
using System.Data.Entity; namespace DataAnnotations
{
internal class TestContext : DbContext
{
public DbSet<Blog> Blogs { get; set; } }
}
上下文中只有Blog集合,没有细节集合。填充与读取代码
private static void populate()
{
using (var context = new TestContext())
{
var blog = new Blog
{
Title = "My First",
BlogDetail = new BlogDetails
{
DateCreated = DateTime.Now,
Description = "这里省略10000字!"
}
}; context.Blogs.Add(blog);
context.SaveChanges();
}
}//void private static void retreive()
{
using (var context = new TestContext())
{
foreach (var b in context.Blogs)
{
Console.WriteLine("{0}.{1}", b.BlogId, b.Title); var d = b.BlogDetail;
Console.WriteLine("{0}.{1}", d.DateCreated, d.Description);
}
}
}//void
数据库表
CREATE TABLE [dbo].[Blogs] (
[BlogId] INT IDENTITY (1, 1) NOT NULL,
[Title] NVARCHAR (MAX) NOT NULL,
[BlogDetail_DateCreated] DATETIME NULL,
[BlogDetail_Description] NVARCHAR (250) NULL,
CONSTRAINT [PK_dbo.Blogs] PRIMARY KEY CLUSTERED ([BlogId] ASC)
);
复杂类型将与引用他的实体一起扁平到一个数据库表中,默认的列名为ComplexTypeName_PropertyName。
示例四
本例演示如何为表和表中的列改名,修改列的数据类型,模型:
using System.ComponentModel.DataAnnotations.Schema; namespace DataAnnotations
{
[Table("InternalBlogs", Schema = "dbo")]
public class Blog
{
public int BlogId { get; set; } [Column("BlogDescription", TypeName = "ntext")]
public string Description { get; set; }
}
}
对应的数据库表为:
CREATE TABLE [dbo].[InternalBlogs] (
[BlogId] INT IDENTITY (1, 1) NOT NULL,
[BlogDescription] NTEXT NULL,
CONSTRAINT [PK_dbo.InternalBlogs] PRIMARY KEY CLUSTERED ([BlogId] ASC)
);
可见,表的名称,列的名称与数据类型都发生的改变。
示例五
数据库通过并发检查和行版本来处理并发,模型代码为:
using System.ComponentModel.DataAnnotations; namespace DataAnnotations
{
public class Blog
{
public int BlogId { get; set; } [ConcurrencyCheck]
public string BloggerName { get; set; } [Timestamp]
public Byte[] TimeStamp { get; set; }
}
}
对应生成的数据库表代码为:
CREATE TABLE [dbo].[Blogs] (
[BlogId] INT IDENTITY (1, 1) NOT NULL,
[BloggerName] NVARCHAR (MAX) NULL,
[TimeStamp] ROWVERSION NOT NULL,
CONSTRAINT [PK_dbo.Blogs] PRIMARY KEY CLUSTERED ([BlogId] ASC)
);
[Timestamp]对应生成了非空的行版本类型,标记了[ConcurrencyCheck]的BloggerName属性会在生成的更新数据库代码的Where子句中添加并发检查。
When SaveChanges is called, because of the ConcurrencyCheck annotation on the BloggerName field, the original value of that property will be used in the update. The command will attempt to locate the correct row by filtering not only on the key value but also on the original value of BloggerName.
CodeFirst建模:DataAnotation的更多相关文章
- 《Entity Framework 6 Recipes》中文翻译系列 (41) ------ 第七章 使用对象服务之标识关系中使用依赖实体与异步查询保存
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 7-7 标识关系中使用依赖实体 问题 你想在标识关系中插入,更新和删除一个依赖实体 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (33) ------ 第六章 继承与建模高级应用之TPH与TPT (2)
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-8 嵌套的TPH建模 问题 你想使用超过一层的TPH继承映射为一张表建模. 解 ...
- Rafy 领域实体框架 - 领域模型设计器(建模工具)设计方案
去年4月,我们为 Rafy 框架添加了领域模型设计器组件.时隔一年,谨以本文,简要说明该领域模型设计器的设计思想. 设计目标 Rafy 实体框架中以领域驱动设计作为指导思想.所以在开发时,以领域建模为 ...
- CodeFirst 的编程方式
第一步:创建控制台项目第二步:添加新建项目→Ado.Net空实体模型第三步:添加实体:Customer,添加几个必要的测试字段第四步:添加实体之间的联系第五步:根据模型生成数据库脚本,并执行sql脚本 ...
- CodeFirst 初恋
CodeFirst 初恋 原著:Prorgamming Entity Framework Entitywork Code First 大家好! 我是AaronYang,这本书我也挺喜欢的,看了一半了, ...
- Entity Framework——建模建库
1数据库初始化策略选择 三种初始化策略: 1)CreateDatabaseIfNotExists:默认的策略.如果数据库不存在,那么就创建数据库.但是如果数据库已存在,而且实体发生了变化,就会出现异常 ...
- 【AaronYang风格】第一篇 CodeFirst 初恋
原著:Prorgamming Entity Framework Entitywork Code First 大家好! 我是AaronYang,这本书我也挺喜欢的,看了一半了,今晚也没 ...
- EntityFramework 基本模式和Code-First的简单使用
1.Database-First Database First就是首先建立好数据库,或者存在现成的数据库也可以.然后在vs中添加ADO.Net实体数据模型,找到需要的数据库和表.它是以数据库设计为基 ...
- MVC5+EF6+MYSQl,使用codeFirst的数据迁移
之前本人在用MVC4+EF5+MYSQL搭建自己的博客.地址:www.seesharply.com;遇到一个问题,就是采用ef的codefirst模式来编写程序,我们一般会在程序开发初期直接在glob ...
随机推荐
- 冒泡排序 and 选择排序 变量打印斐波拉契数列 and 数组打印斐波拉契数列
1 排序 1.1 冒泡排序 #include <stdio.h> int main() { ]; printf("input six int numbers:\n"); ...
- SQL SERVER占用CPU过高排查和优化
操作系统是Windows2008R2 ,数据库是SQL2014 64位. 近阶段服务器出现过几次死机,管理员反馈机器内存使用率100%导致机器卡死.于是做了个监测服务器的软件实时记录CPU数据,几日观 ...
- 升级到Offiec 2016后 Power View 不见了的处理方法
好吧 并不是没有了,而只是快捷方式需要手动的调整出来, 过程还是挺复杂,给一个官方文档吧. Turn on Power View in Excel 2016 for Windows https://s ...
- C++——"%"运算符
基本介绍 r=a%b,余数的取值范围为-b+1~b-1,符号与a一致 要想得到0~b-1的余数,可以用:(a%b+b)%b 数位拆解 方法一:反复的:%10,/10 sizea = 0; while ...
- 九度oj 题目1056:最大公约数
题目1056:最大公约数 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:8068 解决:5317 题目描述: 输入两个正整数,求其最大公约数. 输入: 测试数据有多组,每组输入两个正整数. ...
- 关于oracle 压缩表
这周客户的问题非常多,总是说我的数据不对.于是我对数据梳理了以后发现以前认为是重复数据的,其实并不是,而是我忽略了一个维度.那么这样一来,我们的周详单表就会有500多万的数据.一个月按照4周计算,就要 ...
- 【区间dp+组合数+数学期望】Expression
https://www.bnuoj.com/v3/contest_show.php?cid=9148#problem/I [题意] 给定n个操作数和n-1个操作符,组成一个数学式子.每次可以选择两个相 ...
- 算法(1):查找&排序
算法(Algorithm):一个计算过程,解决问题的方法 程序 = 数据结构+算法 时间复杂度: 当算法过程中出现循环折半的时候,复杂度式子中会出现 O(logn) 时间复杂度小结: 1. 时间复杂度 ...
- POJ 3169_Layout
大早上水一发=.= 题意: n头牛按编号顺序站成一列,给定n头牛之间的位置关系,求出第n头牛和第一头牛之间的最大距离. 分析: 差分约束系统,这题不等式关系还是挺好找的.注意因为按照顺序排列,所以有d ...
- 深入理解hadoop(二)
hadoop RPC 网络通信是hadoop的核心模块之一,他支撑了整个Hadoop的上层分布式应用(HBASE.HDFS.MapReduce), Hadoop RPC具有以下几个特性,透明性(用户本 ...