在上一节中,实现了CodeFirst快速入门。但是很多与数据库的细节还无法自定义。以及使用EF过程中,需要注意的事项。

    在本节中,会涉及到以下

连接字符串

  1个完整的连接字符串  IP:端口\实例名 数据库名组成

  Nuget安装完EF会在*.config的entityFramework节点下添加,表示使用LocalDb数据库,实例名为v11.0。

<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>

  而数据库名,默认为类的全限定名。如下调用父类构造函数,表示数据库名为SaleDb。而不是命名空间+类名。

    public class SaleDb : DbContext
{
public SaleDb():base("SaleDb")
{
}
}

  当然,在这个构造函数里,可以完整的写上完整的连接字符串。

EF的对象状态

  db.Entry(TEntity).State  (附加Entity,并设置状态)

    public enum EntityState
{
// 摘要:
// The entity is not being tracked by the context. An entity is in this state
// immediately after it has been created with the new operator or with one of
// the System.Data.Entity.DbSet Create methods.
Detached = 1,
//
// 摘要:
// The entity is being tracked by the context and exists in the database, and
// its property values have not changed from the values in the database.
Unchanged = 2,
//
// 摘要:
// The entity is being tracked by the context but does not yet exist in the
// database.
Added = 4,
//
// 摘要:
// The entity is being tracked by the context and exists in the database, but
// has been marked for deletion from the database the next time SaveChanges
// is called.
Deleted = 8,
//
// 摘要:
// The entity is being tracked by the context and exists in the database, and
// some or all of its property values have been modified.
Modified = 16,
}

  

延迟加载,贪婪加载,为什么需要Virtual

  延迟加载(lazy load)是(也称为懒加载),延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。可以简单理解为,只有在使用的时候,才会发出sql语句进行查询。

  贪婪加载则是一次性把相关的表也加载进来。

在EF中,默认是支持延迟加载的。

  db.Configuration.LazyLoadingEnabled = false;    //设置禁用延迟加载

如果想单个贪婪加载某个表。则通过Include("表名")

  db.Orders.Include("OrderItems");          //把OrderItems表一并加载进来

Virtual关键字

通常相关连的表作为Entity属性的时候,使用Virtual关键字修饰符。如果不加Virtual关键字,则关联的类只是一个普通的POCO类型。get,set方法为空实现。

使用Virtual关键字后,EF生成一个代理类来重写get和set方法。实现需要的功能。

  

绕过EF,直接SQL查询

  EF作为一个框架,也不可能做到满足所有需求。EF提供了直接操作Ado.net方式。

有三个 API 支持:

  • DbContext.Database.ExecuteSqlCommand
  • DbContext.Database.SqlQuery
  • DbSet.SqlQuery

         

执行sql 返回受影响函数。

public int ExecuteSqlCommand(string sql, params object[] parameters); 

执行sql 返回查询结果并自动映射到指定类上。(不会被EF跟踪状态)

DbRawSqlQuery<TElement> SqlQuery<TElement>(string sql, params object[] parameters);

执行sql 返回查询结果并自动映射到指定类上。(被EF跟踪状态。DbSqlQuery继承自DbRawSqlQuery)

virtual DbSqlQuery<TEntity> SqlQuery(string sql, params object[] parameters);

查看EF生成SQL语句

  当使用EF执行一个复杂的查询时候。我们需要知道EF是否按照我们所需执行。这时,就需要查看EF生成的语句。

  1. 执行IQueryable<T>.ToString(); 即可查看生成的sql语句。
  2. 通过EFProviderWrappers,这里不做赘述。

DataAnnotation

  DataAnnotation 特性由.NET 3.5中引进,给.NET中的类提供了一种添加验证的方式。同时在EF中,也是添加约束与个性化设置一种方式。

常用到以下特性。

  1. KeyAttribute:对应数据库中的主键
  2. RequiredAttribute:对应数据库中字段的数据是否可以为null
  3. MaxLengthAttribute:对应数据库中字符串类型字段的最大长度
  4. MinLengthAttribute:在数据库中无对应,但在代码中字符串最小长度
  5. TimestampAttribute:将列的数据类型指定为行版本
  6. DatabaseGeneratedAttribute:标记指定实体属性是由数据库生成的,并指定生成策略(None数据库不生成值,Identity当插入行时,数据库生成值,Computed当插入或更新行时,数据库生成值)
  7. ColumnAttribute:指定实体属性在数据库中的列名及数据类型
  8. TableAttribute:指定实体类对应的数据表名
  9. ForeignKeyAttribute:指定导航属性的外键字段
  10. NotMappedAttribute:标记指定实体属性在创建数据库中不创建对应字段
  11. ConcurrencyCheck:并发标记
    public class Order
{
[Key]
public int Id { get; set; }
[StringLength(200)]
public string Name { get; set; }
public int UserId { get; set; }
[ForeignKey("UserId")]
public User User { get; set; }
public virtual ICollection<OrderItem> OrderItems { get; set; }
}

  

FluentAPI

  使用DataAnnotation(DA)非常方便,但有时我们的POCO类不希望受到EF的直接关联。或者DA不能满足需求。这时,我们可以使用FluentAPI方式。

  1. HasKey - KeyAttribute:配置此实体类型的主键属性
  2. IsRequired - RequiredAttribute:将此属性配置为必需属性。用于存储此属性的数据库列将不可以为null
  3. HasMaxLength - MaxLengthAttribute:将属性配置为具有指定的最大长度
  4. IsConcurrencyToken - ConcurrencyCheckAttribute:将属性配置为用作开放式并发标记
  5. IsRowVersion - TimestampAttribute:将属性配置为数据库中的行版本。实际数据类型将因使用的数据库提供程序而异。将属性设置为行版本会自动将属性配置为开放式并发标记。
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<AppInfo>().Property(o => o.Id).HasColumnName("AppId");
}

  

MVC异步控制器做个CRUD例子

  微软自家的东西关联总是那么方便。

在MVC5中,添加控制器的时候选择使用EF即自动生成这一切。

建议

  1.模型改变重新生成数据库,导致表数据丢失。

    在使用CodeFirst中,当模型改变的时候,采用第一节中的Nuget中EF Migration API方式则不会清空数据。

  2.是否使用存储过程,视图这些数据库技术。

    当使用EF 这种ORM框架的时候,就应该轻数据库技术,重业务逻辑层。我的建议是万不得已不要使用存储过程,视图实际只是存储了SQL语句。

MVC5代码下载:MVCTest

[ORM] Entity Framework(2) CodeFirst进阶的更多相关文章

  1. [ORM] Entity Framework(1) CodeFirst快速入门

    Entity Framework 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案 对象关系映射(英语:Object Relational Mapping ...

  2. 在Oracle中使用Entity Framework 6 CodeFirst

    项目中需要将系统从SQLServer数据库迁移到Oracle上.由于原大部分数据访问操作都是通过包装了Entity Framework的统一访问入口实现的,所以需要研究Entity Framework ...

  3. [转]Using Entity Framework (EF) Code-First Migrations in nopCommerce for Fast Customizations

    本文转自:https://www.pronopcommerce.com/using-entity-framework-ef-code-first-migrations-in-nopcommerce-f ...

  4. C# ORM—Entity Framework 之Code first(代码优先)(二)

    一.Entity Framework Code first(代码优先)使用过程 1.1Entity Framework 代码优先简介 不得不提Entity Framework Code First这个 ...

  5. C# ORM—Entity Framework 之Database first(数据库优先)&Model First(模型优先)(一)

    一.什么是Entity Framework 1.1 实体框架(EF)是一个对象关系映射器,使.NET开发人员使用特定于域的对象与关系数据.它消除了需要开发人员通常需要编写的大部分数据访问代码.简化了原 ...

  6. Entity Framework - PostgresQL CodeFirst

    经过几年的更新及业界对Entity Framework 的认同. 现在 EF 可以支持的数据库越来越多了.而PostgresQL 数据库现在也可以使用code first的方式来创建数据库了. 不多说 ...

  7. ORM,Entity Framework介绍以及其所包含的基础架构介绍

    一:entity framework 6.0 ORM (实体关系模型) O: Domain Object 领域模型 R: Relational Database 关系型数据库 M: Mapping 映 ...

  8. ASP.NET: Setup a MVC5 website with MySQL, Entity Framework 6 Code-First and VS2013

    The new features available in EF6 allow any developer to build a simple DB-powered website with very ...

  9. Entity Framework:Code-First Tutorial开篇

    这个系列文章是关于Entity Framework Code-First的英文系列文章,内容不错,每篇一个主题知识点介绍,特转载过来 原文地址:http://www.entityframeworktu ...

随机推荐

  1. 基于 Quartz 开发企业级任务调度应用

    原文地址:http://www.ibm.com/developerworks/cn/opensource/os-cn-quartz/index.html Quartz 基本概念及原理 Quartz S ...

  2. Java多线程(3) Volatile的实现原理

    Volatile变量 在程序设计中,尤其是在C语言.C++.C#和Java语言中,使用volatile关键字声明的变量或对象通常拥有和优化和(或)多线程相关的特殊属性.通常,volatile关键字用来 ...

  3. 文档大师 搜狗拼音无法输入汉字_乱码的解决方法_VB6程序

    文档大师用 搜狗拼音无法输入汉字,显示的内容和输入的内容不一致.解决方法: 把中文输入里面的那个“美式键盘”再删掉就好用了,只保留搜狗输入法即可!

  4. Scala 深入浅出实战经典 第67讲:Scala并发编程匿名Actor、消息传递、偏函数解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  5. Codeforces Round #379 (Div. 2) C. Anton and Making Potions 枚举+二分

    C. Anton and Making Potions 题目连接: http://codeforces.com/contest/734/problem/C Description Anton is p ...

  6. linux 文件夹说明,用户添加删除,不熟悉的命令

    一.Linux 根目录下的文件夹说明 usr 程序默认安装路径,相当于windows的 program 附显示当前所处位置:pwd 二.用户 用户添加:useradd 用户名 passwd 用户名 u ...

  7. “You must not call setTag() on a view Glide is targeting” 解决

    报错原因大致是因为Glide加载的iamgeView调用了setTag()方法导致的错误, 因为Glide已经默认为ImageView设置的Tag. 解决办法:自定义一个Application,在里面 ...

  8. 修饰者模式(装饰者模式,Decoration)

    1. 装饰者模式,动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更加有弹性的替代方案. 2.组合和继承的区别 继承.继承是给一个类添加行为的比较有效的途径.通过使用继承,可以使得子类在拥有 ...

  9. [原创]Andorid DexClassLoader的创建过程解析(基于5.0)

    做Android插件框架时,经常会用到dex的动态加载,就要直接或间接的使用DexClassLoader,在new DexClassLoader的时候Android系统做了很多工作,下面我们详细分析一 ...

  10. ora-01031:insufficient privileges解决方法 - 转

    今天晚上要远程修改一个分公司的数据库参数,于是下午先远程过去做些准备工作.数据库是oracle 11g rac,操作系统是windows 2008 server,我还是第一次见过windows下的or ...