ASP.NET MVC

ASP.NET MVC - Entity Framework

实体关系

关系是某个实体(表)的一条记录对应于另一个实体(表)的一条或多条记录。

一对多关系

单方面的包含关系称为一对多,而一对多和一对一其实是一回事,只是站在不同的角度去看就会有不同的结果,比如有员工表和性向表,站在员工角度去看,一个员工对应了一种性向,而站在性向角度去看,一种性向对应于多名员工。

单向一对一

employee引用了sexual

双向一对一

employee引用了sexual,sexual也引用了employee

多对多

双方面的包含关系,称为多对多。一个艺术家对应于多张专辑,一张专辑对应于多个艺术家。通过链表存储对两张表的引用就可以实现多对多关系。

 

EF设计器

创建一个CUI项目,右击项目创建ADO实体数据模型

这会在项目中生成一个edmx文件,双击该文件可以打开实体设计器。

创建EF上下文对象

右击实体设计器- 属性,可以配置EF上下文对象

 

创建实体

右击实体设计器- 新增,可以增加实体

 

创建属性

右击创建好的实体,可以创建以下类型的属性

 

以下创建了一个实体,并添加了两个属性

设置实体集的名称

实体就是一条记录,实体集就是多条记录,实体集对应于数据库的表,在.Net项目中,通过EF上下文对象调用实体集可执行Linq查询。单击实体,可以设置实体集的名称,下面将实体集的名称改为了复数。

根据实体生成数据库

右击设计器 - 根据模型生成数据库

选择新建连接

输入数据库名称 - 确定,这会根据数据库连接自动生成数据库。完成后,数据库就自动建好了。

 

根据数据库生成实体

右击实体设计器 - 从数据库更新模型,这会自动根据数据库创建实体模型。

操作实体

对实体的操作,增删改查都是通过DBContext上下文对象来实现的,它提供了获取实体集(表)的属性。

public void Test( )
{
    DBContext EFContext = new DBContext( );
    //新增
    List<Person> list = new List<Person>
    {
            new Person{ Name="sam" },
            new Person{ Name="leo" }
    };
    EFContext.Persons.AddRange( list ); //or Add
    EFContext.SaveChanges( );

    //查询记录
    var result = EFContext.Persons;

    //删除
    //需要先查询
    EFContext.Persons.RemoveRange( result ); //or Remove
    EFContext.SaveChanges( );
}

实体关系

实体关系在EF中以导航属性的形式存在

一对多关系

一个部门下有多名员工,以下创建两个实体。

右击主键实体 - 新增 - 关联,可以创建一对多关系。一个部门对应多个员工,Person实体出现了一个导航属性Department和一个标量属性DepartmentId,Department实体出现了一个导航属性Peoples,DepartmentId会变成数据库表字段,而导航属性不会变成表字段,导航属性只在你的项目代码中使用,用以表示实体关系。Person作为外键表引用了Department主键表,所以它有一个DepartmentId指向一个部门的Id。

 

EFContext.Deparments.Single( ).Peoples; //一个部门有多个员工
EFContext.Persons.Single( ).Deparment; //一个员工隶属于一个部门

多对多关系

一张专辑有多个艺术家,一个艺术家有多张专辑,双方面的包含关系,称为多对多。

以下创建两种多对多关系,第一种是两个实体相互引用,第二种是两个实体对链表的引用。它们在数据库中生成的表没有什么区别,但在EF设计器中的实体会有一些变化。

第一种多对多关系

DBContext EFContext = new DBContext( );

EFContext.Artists.Add( new Artist
{
    ArtistName = "pink floyd",
    Albums = new List<Album> {
    new Album{ AlbumName="The Division Bell" },
    new Album{ AlbumName="Ummagumma" }
}
} );

EFContext.SaveChanges( );

第二种多对多关系

以一个链表实体存储对双方的引用。

DBContext EFContext = new DBContext( );
ICollection<AlbumLinkArtist> list= EFContext.Artists.Single( ).AlbumLinkArtists; //一个艺术家对应多张专辑,专辑id存储在AlbumLinkArtist表中
ICollection<AlbumLinkArtist> list2 = EFContext.Albums.Single( ).AlbumLinkArtists; //一个专辑对于多个艺术家,艺术家id存储在AlbumLinkArtist表中
//增
var artist = new Artist { ArtistName = "Pink Floyd" };
//为同一个艺术家增加两张专辑
AlbumLinkArtist albumLinkArtist1 = new AlbumLinkArtist
{
    Artist = artist,//同一个艺术家
    Album = new Album { AlbumName = "The Division Bell" }
};
AlbumLinkArtist albumLinkArtist2 = new AlbumLinkArtist
{
    Artist = artist,//同一个艺术家
    Album = new Album { AlbumName = "Ummagumma" }
};

EFContext.AlbumLinkArtists.AddRange( new List<AlbumLinkArtist> {
    albumLinkArtist1,
    albumLinkArtist2
} );
EFContext.SaveChanges( );

//查
foreach (var artist in EFContext.Artists)
{
    Console.WriteLine( artist.ArtistName );
    foreach(var AlbumLinkArtist in artist.AlbumLinkArtist)
    {
        Console.WriteLine( AlbumLinkArtist.Album.AlbumName );
    }
}

如果是从数据库生成实体,那么多对多关系的数据库表在生成实体时会有以上两种情况,如果链表只存储了双方的主键id,则生成第一种多对多,如果链表存储了额外的字段,比如Description,则生成第二种多对多实体,也即会多出一个链表实体。无论是哪种多对多实体,表达的都是一个概念,没有区别,只是我们在使用实体时需要加以区分。

自引用关系

在一些表示分类的具有层级关系的表中,表可能会引用自身来表示父节点和子节点,在设计器中可以先创建节点实体,只指定其主键和名称,先不要增加父节点id,如下:

接着创建自引用关系,右击实体 - 关联,如下设置:

将自动生成的引用Id改为ParentId以便于理解,然后将ParentId设为可为null,因为顶级节点没有父节点。

手动插入记录时注意,不需要指定节点的ParentId,由于实体是面向对象的,所以,节点通过其Childs导航属性的Add方法就可以将其它节点作为子节点添加到自身了。

DBContext EFContext = new DBContext( );
Node father = new Node {  NodeName = "书籍" };
Node child1 = new Node {  NodeName = "哲学" };
Node child1HasChild1 = new Node { NodeName = "性经验史" };
Node child1HasChild2 = new Node { NodeName = "存在与虚无" };

//书籍
//    哲学
//      性经验史
//      存在与虚无

child1.Childs.Add( child1HasChild1 );
child1.Childs.Add( child1HasChild2 );
father.Childs.Add( child1 );
EFContext.Nodes.Add( father );
EFContext.SaveChanges( );

深度查询

//先获取根节点
var roots=EFContext.Nodes.Where( node => node.ParentId == null );
StringBuilder builder = new StringBuilder( );
foreach (var node in roots)
{
    ShowNode( node, 0, builder );
}
Console.WriteLine( builder.ToString( ) );
}

public static StringBuilder ShowNode( Node fatherNode, int deep, StringBuilder builder )
{
builder.Append( new string(' ',deep)+ fatherNode.NodeName+" " );
foreach (var node in fatherNode.Childs)
{
    ShowNode( node, deep+1, builder );
    deep = fatherNode.Childs.Last( ) == node ? 0 : deep;
}
return builder;
}

 

Code First模式

新建一个类库项目,命名为MyEF,添加Entity framework的引用,在项目中创建Model目录用来存放领域模型,右击Model目录添加类。

namespace MyEF.Model
{
    public class Person
    {
        public int PersonId { get; set; }
        public string PersonName { get; set; }
    }
}

创建一个自定义的EF上下文,从DBContext派生

using System.Data.Entity;
using MyEF.Model;

namespace MyEF
{
    public class EFContext : DbContext //自定义EF上下文
    {
        public DbSet<Person> Persons { get; set; } //实体模型必须在此处注册,这就是一张表,记录的集合
      
        public EFContext() : base("name=MyEF") //实例构造函数接收数据库连接字符或数据库名称,如果是连接字符,则是config中的ConnectionString=MyEF
        {

        }

        static EFContext() //静态构造函数可用于指定数据库的创建模式
        {
            //无论怎样,删除同名数据库,再重新创建:
            Database.SetInitializer(new DropCreateDatabaseAlways<EFContext>());
            //默认,参数可为null,当数据库不存在时,自动创建数据库:   
            //Database.SetInitializer ( new CreateDatabaseIfNotExists<EFContext> ( ) ); 
            //如果实体模型发生改变,则先删除同名数据库,再重新创建:
            //Database.SetInitializer ( new DropCreateDatabaseIfModelChanges<EFContext> ( ) );
            // 使数据库保持现状,如果你是后来为已经存在的数据库增加表或表的字段,那么可应用此配置,null表示不做任何改动,但你必须手动Code First增加实体或者为实体增加相应的字段:
            //Database.SetInitializer<EFContext>(null); 或  Database.SetInitializer<EFContext>(new NullDatabaseInitializer<EFContext> );
        }
    }
}

在code first中定义导航属性,导航属性都是类类型且必须修饰为virtual,用以表示实体之间的引用关系。

namespace MyEF.Model
{
    public class Department
    {
        public int DepartmentId { get; set; }
        public string DepartmentName { get; set; }
        public virtual List<Person> Persons { get; set; } //一个部门对应多个员工
    }

    public class Person
    {
        public int PersonId { get; set; }
        public string PersonName { get; set; }
        //此处没有显示创建标量的外键DepartmentId,这样,EF会根据导航属性Department在数据库Person表中自动创建一个外键字段
        public virtual Department Department { get; set; } //一个员工对应一个部门
    }
}

再创建一个控制台引用程序,设置app.config,增加一个数据库连接字符串

<configuration>
<connectionStrings>
  <add name="MyEFConn" connectionString="Data Source=.; Initial Catalog=MyEFDB; Integrated Security=True; MultipleActiveResultSets=True; AttachDbFilename=|DataDirectory|MusicStoreD.mdf"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>
static void Main(string[] args)
{
    //向数据库插入数据时会自动创建表
   // 默认情况下,数据库文件存储在C:Program FilesMicrosoft SQL ServerMSSQL11.MSSQLSERVERMSSQLDATA
    EFContext EFContext = new EFContext();
    Department department = new Department
    {
        DepartmentName = "xxx",
        Persons = new List<Person>
            {
                new Person{ PersonName="sam" },
                new Person{ PersonName="leo" }
            }
    };
    EFContext.Departments.Add(department);
    EFContext.SaveChanges();
}

Code First模式创建实体关系映射

实体间的引用关系是指实体的导航属性与另一个实体关联,下面的方法就是根据导航属性来设置实体间的引用关系。

实体关系的设置分三个步骤

1.创建一个从EntityTypeConfiguration<T>(System.Data.Entity.ModelConfiguration)派生的类型,比如EmployeeConfig.cs文件,然后在这个类型的构造函数中设置实体关系。设置实体关系需要用到以下几个方法,

Has方法设置单方面的引用关系

HasManylambda
//根据实体间一对多的引用关系为另一方生成可null的外键

HasRequiredlambda
//根据实体间一对一的引用关系为当前方生成不可null的外键

HasOptionallambda
//根据实体间一对一的引用关系为当前方生成可null的外键


由于一对一在多数情况下可以当做一对多比如一个名员工对应一个部门但是一个部门也可以对应多个员工所以一对一和一对多没有区别
但也有可能出现这种情况一个员工对应一个住址但一个住址通常都不会对应多个员工
With方法只能在调用了Has方法后才可以调用表示进一步设置引用关系

WithMany[lambda]
//无参版:根据实体间一对多的引用关系为双方都生成可null的外键(如果只有单方面的引用则只生成单方面的外键)

WithOptional[lambda]
//无参版:根据实体间一对一的引用关系为另一方生成可null的外键,如果在此方法后调用了HasForeignKey方法,则表示手动指定另一方的外键(假如你没有指定外键表的哪个键作为外键,那么EF会自动根据主键表的主键为外键表增加一个外键字段)

WithRequired[lambda]
//无参版:根据实体间一对一的引用关系为另一方生成不可null的外键,如果在此方法后调用了HasForeignKey方法,则表示手动指定另一方的外键(假如你没有指定外键表的哪个键作为外键,那么EF会自动根据主键表的主键为外键表增加一个外键字段)
 
HasMany可组合三个With方法,而HasRequired与HasOptional只能组合WithMany方法

2.在EF上下文的派生上下文中重写基类的OnModelCreating方法,将从EntityTypeConfiguration<T>派生的类型注册到配置集合中

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new EmployeeConfig()).Add(/*……*/); //链式操作注册关系配置
}

一对一的code first

如果实体A引用了实体B,但实体B并不引用实体A,这就是单向的一对一。如果实体A引用了实体B,实体B也引用了实体A,这就是双向的一对一。

单向引用:在实体没有外键的情况下由EF自动创建数据库表的外键

public class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
    public virtual Address Address { get; set; }
}

public class Address
{
    public int AddressId { get; set; }
    public string AddressName { get; set; }
}
//一对一的单向引用,EF自动创建数据库表的外键
public class EmployeeConfig : EntityTypeConfiguration<Employee>
{
    public EmployeeConfig()
    {
        HasKey(employee => employee.EmployeeId);
       HasOptional(employee => employee.Address);
        //等同于 :
        HasOptional(employee => employee.Address).WithMany();
    }
}

单向引用:在实体有外键的情况下由你自己手动指定数据库表的外键

public class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
    public int? AddressId { get; set; } //外键可null时,注意必须设为int?,否则抛错
    public virtual Address Address { get; set; }
}

public class Address
{
    public int AddressId { get; set; }
    public string AddressName { get; set; }
}
//一对一的单向引用,手动指定数据库表的外键
public class EmployeeConfig : EntityTypeConfiguration<Employee>
{
    public EmployeeConfig()
    {
        HasKey(employee => employee.EmployeeId);    
        HasOptional(employee => employee.Address).WithMany().HasForeignKey(employee=>employee.AddressId);
    }
}

最后,将配置类注册到配置集合中就OK了。

public class EFContext : DbContext
{
    public DbSet<Employee> Employees { get; set; }
    public DbSet<Address> Addresss { get; set; }

    //……

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new EmployeeConfig()).Add(new AddressConfig());
    }
}

双向引用:在实体没有外键的情况下由EF自动创建数据库表的外键

public class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
    public virtual Address Address { get; set; } //双向引用,则双方实体都必须有导航属性
}

public class Address
{
    public int AddressId { get; set; }
    public string AddressName { get; set; }
    public virtual Employee Employee { get; set; } //双向引用,则双方实体都必须有导航属性
}
//一对一的双向引用,EF自动创建数据库表的外键
public class EmployeeConfig : EntityTypeConfiguration<Employee>
{
    public EmployeeConfig()
    {
        HasKey(employee => employee.EmployeeId);
        //双向引用,双方的外键不可能都是不可null的,如果都是不可null,那么向任何一方插入数据时都必定会抛错
        //所以只可能创建双方外键都可null
        HasOptional(employee => employee.Address).WithMany();
    }
}

双向引用:在实体有外键的情况下由你自己手动指定数据库表的外键

public class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
    public int? AddressId { get; set; } //外键可null时,注意必须设为int?,否则抛错
    public virtual Address Address { get; set; } //双向引用,则双方实体都必须有导航属性
}

public class Address
{
    public int AddressId { get; set; }
    public string AddressName { get; set; }
    public int? EmployeeId { get; set; } //外键可null时,注意必须设为int?,否则抛错
    public virtual Employee Employee { get; set; } //双向引用,则双方实体都必须有导航属性
}
//一对一的双向引用,手动指定数据库表的外键
public class EmployeeConfig : EntityTypeConfiguration<Employee>
{
    public EmployeeConfig()
    {
        HasKey(employee => employee.EmployeeId);
        //手动指定数据库表的外键,这需要在双方的配置类中都显示指定外键才可以
        HasOptional(employee => employee.Address).WithMany().HasForeignKey(employee=>employee.AddressId);
    }
}

public class AddressConfig : EntityTypeConfiguration<Address>
{
    public AddressConfig()
    {
        HasKey(address => address.AddressId);
        //手动指定数据库表的外键,这需要在双方的配置类中都显示指定外键才可以
        HasOptional(address => address.Employee).WithMany().HasForeignKey(address => address.EmployeeId);
    }
}

一对多的code first

在实体没有外键的情况下由EF自动创建数据库表的外键

public class Department
{
    public int DepartmentId { get; set; }
    public string DepartmentName { get; set; }
    public virtual List<Employee> Employees { get; set; }
    public Department()
    {
        Employees = new List<Employee>();
    }
}

public class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
}
//一对多,EF自动创建数据库表的外键
public class DepartmentConfig : EntityTypeConfiguration<Department>
{
    public DepartmentConfig()
    {
        HasKey(department => department.DepartmentId);
        HasMany(department => department.Employees);
        //等同于
        HasMany(department => department.Employees).WithOptional();
    }
}

在实体有外键的情况下由你自己手动指定数据库表的外键

public class Department
{
    public int DepartmentId { get; set; }
    public string DepartmentName { get; set; }
    public virtual List<Employee> Employees { get; set; }
    public Department()
    {
        Employees = new List<Employee>();
    }
}

public class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
    public int? DepartmentId { get; set; }
}
//一对多,手动指定数据库表的外键
public class DepartmentConfig : EntityTypeConfiguration<Department>
{
    public DepartmentConfig()
    {
        HasKey(department => department.DepartmentId);
        HasMany(department => department.Employees).WithOptional().HasForeignKey(employee=>employee.DepartmentId);            
    }
}

多对多的code first

public class Artist
{
    public int ArtistId { get; set; }
    public string ArtistName { get; set; }
    public virtual List<Album> Albums { get; set; }
    public Artist()
    {
        Albums = new List<Album>();
    }
}

public class Album
{
    public int AlbumId { get; set; }
    public string AlbumName { get; set; }
    public virtual List<Artist> Artists { get; set; }
    public Album()
    {
        Artists = new List<Artist>();
    }
}
//多对多,EF自动创建数据库表的外键
public class ArtistConfig : EntityTypeConfiguration<Artist>
{
    public ArtistConfig()
    {
        HasKey(artist => artist.ArtistId);
        //数据库将自动生成一张链表,EF自动创建对两张表的引用外键
        HasMany(artist => artist.Albums).WithMany(album => album.Artists);
    }
}

//多对多,手动指定数据库表的外键
public class ArtistConfig : EntityTypeConfiguration<Artist>
{
    public ArtistConfig()
    {
        HasKey(artist => artist.ArtistId);
        HasMany(artist => artist.Albums).WithMany(album => album.Artists).Map(m => {
            m.ToTable("ArtistAndAlbum");
            m.MapLeftKey("ArtistId");
            m.MapRightKey("AlbumId");
        });
    }
}

自引用的code first

public class Node
{
    public int NodeId { get; set; }
    public string NodeName { get; set; }       
    public int? ParentId { get; set; }
    public virtual Node Parent { get; set; }
    public virtual List<Node> Childs { get; set; }
}
public class NodeConfig : EntityTypeConfiguration<Node>
{
    public NodeConfig()
    {
        HasKey(node => node.NodeId);
        //Node有多个Node
        //当前Node表使用Childs外键引用Node表,外键可null,EF会自动创建一个自动命名的外键
        HasMany(node => node.Childs);
        //手动指定外键
        HasMany(node => node.Childs).WithOptional(node => node.Parent).HasForeignKey(node => node.ParentId);
    }
}

数据库的code first

和先code再生成数据库没有区别,只不过是先有数据库和表,再使用向导完成实体和EF上下文的、映射类的生成。其实数据库的code first应该更灵活,因为你可以随时在数据库更改表字段或增删字段,然后手动更新实体类型的字段即可。如果是使用来自已经创建好的数据库的code first,而数据库表并未定义任何外键关系,那么也可以按照以上方式建立实体在程序中的映射关系,也即如果表没有外键,表与表之间也可以自动关联在一起。如果后来增加了数据库表,那么也只需要在项目中填写一个新的实体即可。

配置实体属性

有两种方式可为属性增加配置,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,则必须配置此特性,否则不会自动生成唯一标识

[System.ComponentModel.DataAnnotations.Schema.ForeignKey]
//设置为外键

[Required]
//不允许空值

[MaxLength(255)]
//最大长度

[MinLength(10)]
//最小长度

[Timestamp]
//并发时间戳,为开放式并发环境配置时间戳。一个实体只能有一个byte [ ] 类型的属性可设置此特性,Sql Server称其为TimeStamp(时间戳),其他数据库称其为RowVersion(行版本)

[ConcurrencyCheck]
//并发非时间戳,当并发冲突发生时,这将为并发提供检查确保不会发生异常。对应的字段类似:public int SocialSecurityNumber { get; set; }
 
[NotMapped]
//不映射到数据库的列,System.ComponentModel.DataAnnotations.Schema

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

创建一个从EntityTypeConfiguration<T>(System.Data.Entity.ModelConfiguration)派生的类型,然后在这个类型的构造函数中设置实体属性的特性,然后重写自定义的EF上下文从基类继承的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()
//字符长度,与数据库表字段的字符长度一样,设为100则生成nvarchar(100)

Property(lambda ).HasColumnType(DBTableColumnType )
//设置字段在数据库表中的列的数据类型,C#有int string datetime类型,但没有数据库表字段的image、text类型,这两个类型可以使用HasColumnType

Property(lambda ).IsRowVersion()
//并发时间戳,为开放式并发环境配置时间戳。一个实体只能有一个byte [ ] 类型的属性可设置此特性,Sql Server称其为TimeStamp(时间戳),其他数据库称其为RowVersion(行版本)

Property(lambda ).IsConcurrencyToken(annotationName , val )
//添加约束
//示例:为多个 字段添加同一个唯一性约束
using System.Data.Entity.Infrastructure.Annotations;
using System.ComponentModel.DataAnnotations.Schema;
Property(lambda ).HasColumnAnnotation(IndexAnnotation.AnnotationName , new IndexAnnotation( new IndexAttribute( "Un_sameRecords" , 1 ) { IsUnique = true } ) );
Property(d => d.TbRightId ).HasColumnAnnotation(IndexAnnotation.AnnotationName , new IndexAnnotation( new IndexAttribute( "Un_sameRecords" , 2 ) { IsUnique = true } ) );

拆分实体到多个表

一个实体拆分成两张表

public class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
    public string EmployeeAddress { get; set; }
}
public class EmployeeConfig : EntityTypeConfiguration<Employee>
{
    public EmployeeConfig()
    {
        HasKey(employee => employee.EmployeeId);          
        Map(m => {
            m.Properties( property => new { property.EmployeeId, property.EmployeeName });
            m.ToTable("Employees");
        })
        .Map(m => {
            m.Properties( property => new { property.EmployeeId, property.EmployeeAddress });
            m.ToTable("EmployeeInfos"); });
    }
}

 

  

 

 

  

待续……

 

 

参考资料

EF里一对一、一对多、多对多关系的配置和级联删除

Entity Framework Code First (五)Fluent API - 配置关系

《Entity Framework 6 Recipes》中文翻译系列 

//双向引用

原文地址:https://www.cnblogs.com/myrocknroll/p/8625923.html