.NET - EntityFramework 实体关系数据模型

EntityFramework 实体关系数据模型(DO.NET Entity Framework)

ADO.NET Entity Framework 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案。该框架曾经为.NET Framework的一部分,但version 6之后从.NET Framework分离出来。

在项目中使用Entity Framework

要得到最高版本的Entity Framework 程序包,可以通过扩展与更新或者右击项目-引用-管理NuGet程序包。

创建Entity实体关系模型

右击项目 - 添加 - 数据 - ADO.NET实体数据模型

来自数据库的EF设计器:通过已经事先创建的数据库和表,EF框架自动根据数据库生成表实体。

空EF设计器模型:通过EF设计器的可视化界面设计实体关系图,EF框架自动根据关系图生成数据库、表和对应的实体类。

Code First模型:通过全手工创建实体,运行代码后自定生成数据库和表。

添加完成后在项目中会包含一个后缀为edmx文件,此文件描述模型的架构。这三个文件分别是模型的XML表示,数据库构架的XML表示、映射表与实体的关系的XML表示。

xxx.context.tt(数据库操作上下文)

xxx.tt(实体模型)

Code First模式

DbContext类(System.Data.Entity.DbContext)

这是一个操作实体的上下文对象,它比ObjectContex更轻量级,推荐使用DbContext。DbContext内部维护了数据库连接、管理实体数据、生成数据库操作语句、将数据持久化到数据库。它包含所有的实体对象的集合(可查询数据集),通过它的泛型集合属性DbSet<T>存储这些数据集。你所创建的类是如何成为Entity实体的呢?很简单,完成以下三步:

1.创建一个类库,命名为DataAccess,用以表示数据访问层,创建一个BreakAwayContext的类,使其从DbContext派生。键入以下代码:

using System.Data.Entity;
using Model;

namespace DataAcess
{
    public class BreakAwayContext : DbContext
    {
        public BreakAwayContext ( ) : base ( "name=DBConnection" ) { } //name=配置文件中的数据库连接字符串的名称
        public DbSet<Destination> Destinations { get; set; } //你创建的实体类Destination,实体代表了一张表,此处通过DbSet泛型集合表示该表的所有记录
        public DbSet<Lodging> Lodgings { get; set; } //你创建的实体类Lodging,实体代表了一张表,此处通过DbSet泛型集合表示该表的所有记录

//使用此静态构造函数指定数据库的初始化方式,无论如何请先关闭打开的数据库、关闭vs中的服务器资源管理器中的数据库连接,否则以下任务不会完成
        static BreakAwayContext ( )
        {
            Database.SetInitializer ( new CreateDatabaseIfNotExists<BreakAwayContext> ( ) ); //默认,参数可为null,当数据库不存在时,自动创建数据库          
            Database.SetInitializer ( new DropCreateDatabaseAlways<BreakAwayContext> ( ) ); //无论怎样,删除同名数据库,再重新创建
            Database.SetInitializer ( new DropCreateDatabaseIfModelChanges<BreakAwayContext> ( ) ); //如果实体模型发生改变,则先删除同名数据库,再重新创建
        }
    }
}

DataAccess

2.创建一个类库,命名为Model,用以表示实体层,创建两个实体类:Destination和Lodging。前者表示旅行的目的地,后者表示住宿。键入以下代码:

namespace Model
{
    /// <summary>
    /// 目的地
    /// </summary>
    public class Destination
    {
        public int DestinationId { get; set; }
        public string Name { get; set; }
        public string Country { get; set; }
        public string Description { get; set; }
        public byte [ ] Photo { get; set; }
        //Lodgings集合是Lodging类,该表会被识别为外键表,因为这表示了一个Destination(目的地)对应多个Lodgings(住宿)的关系。
        public List<Lodging> Lodgings { get; set; }
    }
}

Destination

namespace Model
{
    /// <summary>
    /// 住宿
    /// </summary>
    public class Lodging
    {
        public int LodgingId { get; set; }
        public string Name { get; set; }
        public string Owner { get; set; }
        public bool IsResort { get; set; }
        //作为外键引用了Destination表的主键,此处可以写成public Destination Destination,效果是一样的,都会被识别为对Destination表的主键的引用
        public int DestinationId { get; set; }
    }
}

Lodging

3.创建一个控制台应用程序,命名为BreakAwayConsole,用以表示显示层。添加对Entity framework的引用,这样会自动在App.config中生成默认的数据库配置信息节点:<entityFramework>,将其全部删除,再添加一个ConnectionString,configSections好像必须是configuration的第一个配置节,所以ConnectionString配置节只能放在configSections后面。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
          <connectionStrings>
                    <add name="DBConnection" 
                            connectionString="Data Source=(local); Database=stuEntity; User ID=sa; Password=123456; MultipleActiveResultSets=True" 
                            providerName="System.Data.SqlClient" />
          </connectionStrings>
</configuration>

app.config

4.添加DataAccess对Model的引用,添加BreakAwayConsole对DataAccess和Model的引用后,在控制台中创建一条记录并插入数据库,此时DbContext会自动为你创建数据库和表。

using DataAccess;
using Model;

namespace BreakAwayConsole
{
    class Program
    {
        static void Main ( string [ ] args )
        {
            var destination = new Destination ( )
            {
                Country = "美国" ,
                Description = "风城" ,
                Name = "芝加哥"
            };
            using ( var context = new BreakAwayContext ( ) )
            {
                context.Destinations.Add ( destination );
                context.SaveChanges ( );
            }
        }
    }
}

控制台.program

ctrl+F5运行程序,等待片刻数据库就创建完毕了。

字段属性映射的默认约定

属性与主键约定:Id或类名Id将默认自动映射为主键。

属性与字符约定:字符类型的属性默认自动映射为nvarchar(max) null。

属性与bool约定:布尔值类型的属性默认自动映射为bit

属性与byte数组约定:byte数组类型的属性默认自动映射为varbinary ( max)

集合属性与主外键约定:泛型集合中的类会被视为外键表,外键表总是有一个外键引用了当前具有泛型集合的类,外键可以是一个int也可以直接是它所引用的类类型。如下:

public int DestinationId { get; set; }
public Destination Destination { get; set; }

配置实体字段属性

有两种方式可为字段增加描述性配置,Data Annotations和Fluent API,前者使用简单,后者提供更强大的清洁的配置。(如果不喜欢到处贴标签)

1.Data Annotations配置(System.ComponentModel.DataAnnotations)

[Table ( "Animal" )] 
//将类映射为Animal表
[Key]
//主键,且种子增量每次+1,即自动增长,增量为1
[Key, DatabaseGenerated ( System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity )]
//如果主键类型是Guid,则必须配置此特性,否则不会自动生成唯一标识
[Required]
//不允许空值
[MaxLength ( 255 )]
//最大长度
[MinLength ( 10 )]
//最小长度
[Timestamp]
//并发时间戳,为开放式并发环境配置时间戳。一个实体只能有一个byte [ ] 类型的属性可设置此特性,Sql Server称其为TimeStamp(时间戳),其他数据库称其为RowVersion(行版本)
[ConcurrencyCheck]
//并发非时间戳,当并发冲突发生时,这将为并发提供检查确保不会发生异常。对应的字段类似:public int SocialSecurityNumber { get; set; }

配置实体字段属性

2.Fluent API配置 (System.Data.Entity.ModelConfiguration和System.Data.Entity)

System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<T>泛型类用以配置实体的属性,将其映射为数据库表字段的特性。为此,你应该创建一个表示为实体类增加配置的类,接着通过在构造函数中初始化这些配置信息。然后重写DbContext的OnModelCreating()方法,该方法会在创建表之前将配置信息应用到数据库,所以将每一个实体类的配置信息注册在modelBuilder.Configurations集合中即可。

ToTable ( tableNameString)
//设置映射为数据库的表名
HasKey ( lambda)
//主键,且种子增量每次+1,即自动增长,增量为1
HasPrecision ( n1, n2)
//为decimal类型的属性保留有效位数和小数位数,n1为有效位数,n2为小数位数
Property ( lambda).HasDatabaseGeneratedOption ( System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity )
//如果主键类型是Guid,则必须配置此项,否则不会自动生成唯一标识
Property ( lambda).IsRequired ( )
//允许空
Property ( lambda).HasMaxLength ( )
//字符长度
Property ( lambda).HasColumnType ( "image" )
//列类型为二进制图像数据
Property ( lambda).IsRowVersion ( )
//并发时间戳,为开放式并发环境配置时间戳。一个实体只能有一个byte [ ] 类型的属性可设置此特性,Sql Server称其为TimeStamp(时间戳),其他数据库称其为RowVersion(行版本)
Property ( lambda).IsConcurrencyToken ( )
//并发非时间戳,当并发冲突发生时,这将为并发提供检查,确保不会发生异常。对应的属性字段的类型为int

配置实体字段属性

using System.Data.Entity.ModelConfiguration;
using System.Data.Entity;
using Model;

namespace DataAcess
{
    //Destination表的列配置
    public class DestinationConfiguration : EntityTypeConfiguration<Destination>
    {
        public DestinationConfiguration ( )
        {
            ToTable ( "Destination" ); 
            HasKey ( d => d.DestinationId ); 
            Property ( d => d.Name ).HasMaxLength ( 255 ).IsRequired(); 
            Property ( d => d.Description ).HasMaxLength ( 255 ).IsRequired ( ); 
            Property ( d => d.Photo ).HasColumnType ( "image" );
        }
    }

//Lodging表的列配置
    public class LodgingConfiguration : EntityTypeConfiguration<Lodging>
    {
        public LodgingConfiguration ( )
        {
            //……
        }
    }
    public class BreakAwayContext : DbContext
    {
        //使用此静态构造函数指定数据库的初始化方式,无论如何请先关闭数据库,否则以下任务不会完成
        static BreakAwayContext ( )
        {
            Database.SetInitializer ( new CreateDatabaseIfNotExists<BreakAwayContext> ( ) ); //默认,参数可为null,当数据库不存在时,自动创建数据库          
            Database.SetInitializer ( new DropCreateDatabaseAlways<BreakAwayContext> ( ) ); //无论怎样,删除同名数据库,再重新创建
            Database.SetInitializer ( new DropCreateDatabaseIfModelChanges<BreakAwayContext> ( ) ); //如果实体模型发生改变,则先删除同名数据库,再重新创建
        }

public BreakAwayContext ( ) : base ( "name=DBConnection" ) { } //name=配置文件中的数据库连接字符串的名称
        public DbSet<Destination> Destinations { get; set; } //你创建的实体类Destination,实体代表了一张表,此处通过DbSet泛型集合表示该表的所有记录
        public DbSet<Lodging> Lodgings { get; set; } //你创建的实体类Lodging,实体代表了一张表,此处通过DbSet泛型集合表示该表的所有记录

//实体被映射为表之前OnModelCreating会被运行,这将进行列配置检查并应用列配置
        protected override void OnModelCreating ( DbModelBuilder modelBuilder )
        {
            modelBuilder.Configurations.Add ( new DestinationConfiguration ( ) ); //注册Destination表的列配置
            modelBuilder.Configurations.Add ( new LodgingConfiguration ( ) ); //注册Lodging表的列配置
        }
    }
}

示例

实体关系的默认约定

假设有X和Y两个类。

//一对一:两个类分别包含对方的一个引用
namespace Model
{
    public class X
    {
        public int XId { get; set; } //主键
        public Y y { get; set; } //引用Y
    }

public class Y
    {
        public int YId { get; set; } //主键
        public X x { get; set; } //引用X
    }
}

一对一

// 一对多:两个类中分别包含一个集合属性和一个引用
namespace Model
{
    public class X
    {
        public int XId { get; set; } //主键
        public List<Y> Ys { get; set; } //一对多,一个X对多个Y 
    }

public class Y
    {
        public int YId { get; set; } //主键
        public X x { get; set; } // 作为外键引用X 
    }
}

一对多

//多对多:两个类分别包含对方的一个集合属性
namespace Model
{
    public class X
    {
        public int XId { get; set; } //主键
        public List<Y> Ys { get; set; } 
    }

public class Y
    {
        public int YId { get; set; } //主键
        public List<X> Xs { get; set; } 
    }
}

多对多

配置实体关系

HasRequired ( lambdaForForeignKey )
//设置当前表的哪个字段为必须的外键,该字段不可以为null
HasOptional( lambdaForForeignKey )
//设置当前表的哪个字段为不必须的外键,该字段可以为null
//示例:
//通常情况下应在外键表写关系 
HasRequired ( b => b.User );//当前表的哪个字段作为必须的外键并且是不可以为null的
HasOptional ( b => b.User ); //当前表的哪个字段作为不必须的外键并且是可以为null的
HasRequired ( b => b.User ).WithMany ( ); //当前表的哪个字段作为必须的外键并且是不可以为null的(HasRequired),该外键表对主键表的引用也可以是多个外键引用同一个主键(WithMany)

配置实体关系

示例

//Lodging表的列配置
public class LodgingConfiguration : EntityTypeConfiguration<Lodging>
{
    public LodgingConfiguration ( )
    {
        HasRequired ( l=>l.Destination ); //外键不可以为null
        Property ( l=>l.Name ).HasMaxLength ( 20 ).IsRequired ( ); //可空字段
    }
}

示例

时间: 2024-11-05 15:48:34

.NET - EntityFramework 实体关系数据模型的相关文章

PowerDesinger:实体关系图-&gt;物理数据模型(关系表)-&gt;sql语句-数据库

之前参加项目的时候,就听说过PowerDesinger,但一直都没有用到过,这次通过接手基础的选课模块终于有机会通过powerDesinger的CDM模型创建数据库了. PowerDesinger中存在几种数据模型分别是:M----Model, 概念数据模型(CDM)Conceptual Diagram Model 逻辑数据模型(LDM) 物理数据模型(PDM)Physical Diagram Model 面向对象模型(OOM) 业务流程模型(BPM) 抽象程度(依次降低): CDM->LDM-

SqlServer示例数据库Northwind(一)——实体关系

在学习Spss统计分析.EA画实体关系图.PowerDesigner画数据库模型图等时,苦于找不到一个好的实例.由于实际工作中项目使用的表结构属于公司的商业保密内容,且在和大家交流时,其结构大家也不熟悉:而使用简单创建的Teacher.Student.Class等数据模型时,建表.录数据也是一个麻烦事:使用SqlServer的示例数据库正好,大伙都熟悉,又是现成的. 很多书籍.教程都使用Northwind数据库作为模型,但我一直对它不甚了解,今天特意下载后了解了一下,现在简单的记录下笔记,以后依

关系数据模型

一.数据结构 关系数据模型是有若干个关系模式组成的集合.关系模式的实例成为关系.每个关系可看为一个二维表,表的行称为元组,用来标识实体集中的一个实体:表的列称为属性,列名即为属性名,属性名不能相同. 关系的描述称为关系模式(Relation Schema)它可以形式化地表示为: R(U,D,dom,F) 其中R为关系名,U为组成该关系的属性名集合,D为属性组U中属性所来自的域,dom为属性向域的映象集合,F为属性间数据的依赖关系集合. 通常简记为: R(U)或R(A1,A2,…,An) 其中R为

逻辑数据模型之层次数据模型、网状数据模型和关系数据模型

上一篇文章简单介绍了概念数据模型.逻辑数据模型.物理数据模型的基本概念.特性以及三者所对应的数据库的开发阶段.现在针对逻辑数据模型中所用到的三种数据模型---层次数据模型.网状数据模型以及关系数据模型做一个相信的介绍与对比分析. 一.层次数据模型 定义:层次数据模型是用树状<层次>结构来表示实体类型和实体间联系的数据模型.(来自百度百科) 其实层次数据模型就是的图形表示就是一个倒立生长的树,由基本数据结构中的树(或者二叉树)的定义可知,每棵树都有且仅有一个根节点,其余的节点都是非根节点.每个节

数据库原理及应用-数据模型之关系数据模型

2018-02-04 23:03:28 一.关系数据模型 关系型数据模型的基本的数据结构只有一种:表(relation).在关系数据模型中将现实世界中的实体以及实体的联系都用表来表达,而层次数据模型中是用记录来表示实体,PCR表示关系,网状数据类型中是用记录来表示实体,系来表示关系,关系型数据模型将两者统一采用表来表达,这是一个很大的区别. 关系模型的特性: 基于集合论的知识,有更高的抽象级别 屏蔽掉底层的实现算法,容易理解 引入关系代数系统 引入结构化的查询语言 Soft link,软连接,通

概念模型、数据模型、关系数据模型

概念模型和数据模型 数据模型的定义 关系数据模型

实体关系映射

一.实体关系概述        实体关系是指实体与实体之间的关系,从方向上分为单向关联和双向关联:从实体数量上分一对一,一对多和多对多.1.实体关系的方向性 (1)单向关联    单向关联是一个实体中引用了另外一个实体.简单地说,就是通过一个实体可以获得另一个实体对象.例如,实体A对实体B的单向关联.实体A的代码如下: ? 1 2 3 4 5 6 7 8 9 10 public class EntityA {<span style="font-family:Verdana;"&g

如何用Visio画数据库实体关系图

在百度经验中浏览:http://jingyan.baidu.com/article/e4511cf3374a862b855eaf58.html 在设计数据库表结构时,通常都是先画数据库实体关系图,这样在讨论设计的是否合理时,可以很容易看懂数据表之间的关系. 打开Microsoft Office Visio 2007,左侧的模板类别中选择"软件和数据库",双击右侧的"数据库模型图". 调整显示比例 添加实体:鼠标指针移动到实体上,按下鼠标左键不要松开,移动鼠标到右侧的

hibernate 实体关系映射笔记

@常用属性说明: @Entity:实体类 @Table:指定对应数据表 @Id:主键,使用可以为null值的类型,如果实体类没有保存到数据库是一个临时状态 @Column:配置普通属性,除了主键外,java基本类型的属性 @Base:普通属性的加载方式 @GeneratedValue:主键生成策略 @Temporal:日期类型(DATE,TIME还是TIMESTAMP),如果属性类型是java.util.Date(是以上3个类的父类)类型时才需要使用该@声明具体的日期类型 @Transient: