标签:
我们在开发项目的时候,项目可能已经有了对应的数据库,也可能完全没有数据库需要我们从零开始,还有可能是我们收下了一个别人的烂摊子,需要我们自己做些修正。说真的,无论什么还是原装的比较好一点。现在先看下,如何不使用任何配置文件和注释代码(注解)实现,EF操作数据库。
1.根据你的需要,创建一个项目
2.在启动项目中的config文件添加一个指向目标数据库的连接字符串,数据库是否存在没有任何关系。
3.编写若干实体类,编写属性。这里有一个注意的地方:主键属性必须命名为-类名+Id.为什么需要这么做,这是因为EF是基于“约定优先”设计的,而且追求的是使用最少的注解(原:注释)和配置。
例:
public class ExamQuestion { public int ExamQuestionId { get; set; } public int KnowledgeModelId { get; set; } public string Name { get; set; } public string Context { get; set; } /// <summary> /// 知识水平 /// </summary> public int Level { get; set; } /// <summary> /// 难度 /// </summary> public int DifficultLevel { get; set; } /// <summary> /// 知识点 /// </summary> public KnowledgeModel Knowledge { get; set; } }
另一个实体类:
/// <summary> /// 知识结构 /// </summary> public class KnowledgeModel { public int KnowledgeModelId { get; set; } public string Name { get; set; } public string Context { get; set; } public KnowledgeType Type { get; set; } public KnowledgeModel FatherPoint { get; set; } /// <summary> /// 考试题目 /// </summary> public List<ExamQuestion> ExamPoints { get; set; } public ListChildrenPoints { get; set; } public string Version { get; set; } } /// <summary> /// 结构类型 /// </summary> public enum KnowledgeType { Project, Part, Charpter, Point }
然后就是正文-最主要的地方了:
public class DemoContext:DbContext { public DbSet<ExamQuestion> ExamPoints { get; set; } public DbSet<KnowledgeModel> Knowledges { get; set; } public DemoContext() : base("ModelContext") { } }
“ModelContext”则是需要替换成自己添加的连接字符串名称的。
DemoContext类则是操作数据库的主要接口。通常的操作方法就是使用 Linq to DbSet<T>,这些可以满足基本的数据库操作了。当然,因为有时候我们可能会遇到一些特殊的查询操作,比如说联合查询。(父类)DbContext定义了一个Database属性,可以在这个属性下找到方法ExecuteSqlCommand以及它的异步版本ExecuteSqlCommandAsync ,这对方法支持直接执行SQL语句,以及参数化,甚至可以开始事务。
等下,数据库呢?当我们在主程序new一个DemoContext对象之后,并向ExamPoints和Knowledges集合中添加对象,EF会在这个时候自动按照查找到的匹配方案自动创建表(第一次启动)。在这个过程中,如果出现不符合规则的错误就会报错。当然,因为是使用EF默认规则,所以最有可能的就是主键规则不正确,意思就是,你的属性中没有一个名字是 “类名+Id(或ID)”。
在示例代码中,我添加了很多集合以及其他类的引用,但是我没有特意为它们指定外键或创建关系表,那么EF是怎么处理的呢?
我们先来看看EF生成了哪些表:
其中_MigrationHistory表是用来记录数据库迁移版本的表,作用未知,原理未知(可能会经历了深入研究之后会明白),暂时这个表跟我们现在的关系关联不大。
那么,看下其他的表,不出所料,名称是类名的复数形式(-s)。不得不说,英语真是一个别扭的东西。
然后,查看一下表的定义:
1.ExamQuestions:
CREATE TABLE [dbo].[ExamQuestions] ( [ExamQuestionId] INT IDENTITY (1, 1) NOT NULL, [KnowledgeModelId] INT NOT NULL, [Name] NVARCHAR (MAX) NULL, [Context] NVARCHAR (MAX) NULL, [Level] INT NOT NULL, [DifficultLevel] INT NOT NULL, CONSTRAINT [PK_dbo.ExamQuestions] PRIMARY KEY CLUSTERED ([ExamQuestionId] ASC), CONSTRAINT [FK_dbo.ExamQuestions_dbo.KnowledgeModels_KnowledgeModelId] FOREIGN KEY ([KnowledgeModelId]) REFERENCES [dbo].[KnowledgeModels] ([KnowledgeModelId]) ON DELETE CASCADE );
2.KnowledgeModels:
CREATE TABLE [dbo].[KnowledgeModels] ( [KnowledgeModelId] INT IDENTITY (1, 1) NOT NULL, [Name] NVARCHAR (MAX) NULL, [Context] NVARCHAR (MAX) NULL, [Type] INT NOT NULL, [Version] NVARCHAR (MAX) NULL, [FatherPoint_KnowledgeModelId] INT NULL, CONSTRAINT [PK_dbo.KnowledgeModels] PRIMARY KEY CLUSTERED ([KnowledgeModelId] ASC), CONSTRAINT [FK_dbo.KnowledgeModels_dbo.KnowledgeModels_FatherPoint_KnowledgeModelId] FOREIGN KEY ([FatherPoint_KnowledgeModelId]) REFERENCES [dbo].[KnowledgeModels] ([KnowledgeModelId]) );
原谅我的SQL学的不怎么样,EF为我们做了这么几件事,a.创建表和字段 ;b.将名称为类名+id的字段设为主键,因为我在定义表的时候使用了int,所以也自动增加了自增队列;c.创建对主键的索引(CLUSTERED是这个意思吧?);d.检索类中对其他类的引用创建外键,如果是集合,则在集合元素的类所对应的表中创建外键,如果是单个引用,则在自己的类里创建外键关联,如果双方都是集合引用对方,则会创建一个第三方的关系表保存引用关系。
这些已经可以满足一个微小型项目的需求。
注: 需要注意的地方就是,如果数据库连接直接指向一个数据库文件,同时,这个数据库文件附加到了项目中,就会出现 EF访问的数据永远是最新的,当然Web项目除外。这是因为可执行项目在编译的时候会把附加到项目中的文件全部拷贝到debug文件夹下,然后访问或执行(大概),所以指向的数据库文件会被刷新。以上都是我的猜测,等以后有机会研究下为啥吧。
第二章 Entity Framework -- Code First入门
标签:
原文地址:http://my.oschina.net/c7jie/blog/521573