全国服务热线:4008-888-888

行业新闻

EntityFramework Core投射关联详细说明

这时大家从Blog看来,一个Blog下相匹配好几个Post,而一个Post相匹配只归属于一个Blog,这时配备关联以下:


CONSTRAINT [PK_Post] PRIMARY KEY ([Id]), CONSTRAINT [FK_Post_Blog_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [Blog] ([Id]) ON DELETE CASCADE ); 复制代码 这时大家可以很确立的见到针对Post表上的BlogId创建外键约束BlogId,也便是相匹配的Blog表上的主键即Id,同时后边得出了DELETE CASADE即开展联级删掉的标志,换句话说当删掉了Blog上的数据信息,那麼这时Post表上相匹配的数据信息也会开展相对的删掉。同时在转化成SQL句子时,还对Post上的BlogId建立了数据库索引,以下:

CREATE INDEX [IX_Post_BlogId] ON [Post] ([BlogId]);
由上知,针对一对多关联中的外键约束,EF Core会默认设置建立其数据库索引,自然这儿的数据库索引毫无疑问是是非非唯一非集聚数据库索引,集聚数据库索引为其主键。大家根据数据信息库上便可以见到,以下:

这时即便大家配不上置特定外键约束为BlogId一样也没问题,以下:

b.HasMany(m = m.Posts).WithOne(o = o.Blog);
由于所述大家早已确立写成了BlogId,可是EF Core仍然能够为其特定BlogId为外键约束,如今大家相反想,如果大家将Post中的BlogId删掉,一样开展所述投射是不是管用呢,历经具体认证的确是能够的,以下:

别心急下结果,大家再说看一种状况,如今大家开展以下配备并去除Post中的BlogId還是否仍然管用呢?

b.HasMany(m = m.Posts);
历经临床医学验证,也是管用的,可以恰当表述大家要想的实际效果并全自动加上了外键约束BlogId列,因此到这儿大家能够为一对多关联下一个结果:

一对多关联结果 在一对多关联中,大家能够根据投射确立特定外键约束列,还可以不特定,由于EF Core內部会搜索是不是早已特定其外键约束列有则立即用特定的,沒有则全自动转化成一个外键约束列,列名叫外键约束列所属的类名+Id。同时针对一对多关联大家能够立即只应用HasMany方式来配备投射而不用另配置HasOne或是WithOne,所述皆是以顺向视角去配备投射,由于便于了解,自然相反亦然。

One-One RelationShip (一对一关联) 针对一对一关联和多对多关联略微繁杂一点,大家来每个击破,大家根据举例说明例如一个商品只归属于一个归类,而一个归类下仅有一个商品,以下:


这时大家根据& ef migrations add Initial 原始化就早已出現以下不正确:

大约含意为未确立Product和Category到底是谁依靠项,未确立特定造成出現所述不正确。而所述针对一对多关联则不容易出現这般不正确,细心剖析不会太难发觉一对多早已确立到底是谁行为主体,而针对一对一关联两者为逐一相匹配关联,因此EF Core没法分辨其行为主体,因此务必大家手动式去特定。这时大家若开展以下特定你能发觉沒有lambda表述式提醒:

 b.HasOne(o = o.Category)
 .WithOne(o = o.Product)
 .HasForeignKey(k= k.)
還是由于行为主体关联的缘故,大家還是务必特定泛型主要参数才能够。以下所显示:

 b.HasOne(o = o.Category)
 .WithOne(o = o.Product)
 .HasForeignKey Category (k = k.ProductId);
这时在Category上建立ProductId外键约束,同时候对ProductId建立以下的唯一非集聚数据库索引:

CREATE UNIQUE INDEX [IX_Category_ProductId] ON [Category] ([ProductId]);

多对多关联在EF Core以前版本号有立即应用的方式如HasMany-WithMany,可是在EF Core中则已不出示相匹配的方式,想一想多对多关联還是能够根据一对多能够获得,例如一个商品归属于好几个归类,而一个归类相匹配好几个商品,典型性的多对多关联,可是根据大家的叙述则彻底能够根据一对多关联而投射获得,下边大家一起來看一下:


public int ProductId { get; set; } public IEnumerable ProductCategory ProductCategorys { get; set; } } 复制代码
所述大家将得出第三个关系类即ProductCategory,将Product(商品类)和Category(归类类)关系到ProductCategory类,最后大家根据ProductCategory来开展投射,以下:


好啦来到这儿才行,有关三种投射关联大家详细介绍完后,不是是从此完毕了,远远地并不是,下边大家再说别的特性投射。

有关键投射中的外键约束投射所述早已探讨过,下边大家来说讲别的种类键的投射。

预留键/可选择键投射(HasAlternateKey) 预留键/可选择键能够为一个实体线类配备除主键以外的唯一标志,例如在登陆选用户名能够做为客户的唯一标志除开主键标志外,这一情况下大家能够为UserName配备可选择键,打个比如那样一个情景:一个客户只有选购一这书,在Book表格中配备一个主键和客户Id(事例尽管不太适当却能非常好叙述可选择键的应用情景)

 public class Book
 public int Id { get; set; }
 public string UserId { get; set; }
 }
下边大家根据可选择键来配备客户Id的投射


假如大家要想一个外键约束引入一个特性而并不是主键,这时大家能够根据行为主体键投射来开展配备,这时配备行为主体键投射身后具体上全自动将其设定为一个可选择键。这一也不用大家多讲了。

好啦到此才行大家说完了键投射,接下去大家再说叙述特性投射:

特性投射 针对C#中string种类若大家不开展配备,那麼在数据信息库文件将默认设置设定为NVARCHAR而且长短为MAX且是为可空,以下:

若大家必须设定其长短且为非空,这时必须开展以下配备:

b.Property(p = p.Name).IsRequired().HasMaxLength(50);
根据HaxMaxLength方式来特定较大长短,根据IsRequired方式来特定为非空。可是这时难题来啦,数据信息库种类针对string有VARCHAR、CHAR、NCAHR种类,那麼大家理应怎样投射呢?例如针对VARCHAR种类,在EF Core中针对数据信息库列种类大家能够根据 HasColumnType 方式来开展投射,那麼假定针对数据信息库种类为VARCHAR长短为50且为非空,大家是不是能够开展以下投射呢?

 b.Property(p = p.Name)
 .IsRequired()
 .HasColumnType( VARCHAR )
 .HasMaxLength(50);

根据所述转移错误,大家改动成以下才恰当:

b.Property(p = p.Name)
 .IsRequired()
 .HasColumnType( VARCHAR(50) 
处理一个,又来一个,那麼针对枚举类型种类大家又该开展怎样投射呢,枚举类型相匹配数据信息库文件的种类为TINYINT,大家开展以下设定:


public Type Type { get; set; } public IEnumerable ProductCategory ProductCategorys { get; set; } public enum Type [Description( 一般 )] General = 0, [Description( 商业保险 )] Insurance = 1 } 复制代码
【留意】:这时将其投射成枚举类型没问题所述早已演试,可是当我们们获得数据信息时将TINYINT变换成枚举类型时将出現以下不正确:

归根结底TINYINT相匹配C#中的byte类最终试着将其变换为int才会造成变换不成功,因此在界定枚举类型时还记得将其承继自byte,以下才管用:


说完如公映射后,大家再说讲下默认设置值投射。 当我们们敲默认设置投射会发觉有2个,一个是HasDefaultValue,一个是HasDefaultValueSql,大家一起來看一下究竟怎样用:

大家在Product类中加上Count字段名:

 public int Count { get; set; }

针对默认设置值投射小结起來就一句话:针对C#中的种类和数据信息库种类一致得话用HasDefaultValue,不然请用HasDefaluValueSql。

【留意】:针对字段名种类投射有一个奇怪例外,针对时间种类DateTime,在数据信息库文件也存有其相匹配的种类datetime,可是假如大家不手动式特定种类会默认设置投射成更精准的时间种类即datetime2(7)。

大家在Product类中加上建立時间列,以下:

 public DateTime CreatedTime { get; set; }
这时大家不特定其投射种类,这时大家见到在数据信息库文件的种类为datetime2(7)

自然之上投射也没有什么难题,可是针对大部分分针对时间种类全是投射成datetime且给定默认设置時间为当今時间,因此这时必须手动式开展配备,以下:

b.Property(p = p.CreatedTime)
 .HasColumnType( DATETIME )
 .HasDefaultValueSql( GETDATE() );
讲完默认设置值必须留意的难题,大家再说讲下测算列的投射,在EF Core中针对测算列投射,在以前版本号为ForSqlServerHasComputedColumnSql,现阶段是HasComputedColumnSql。比如以下它是测算列:

 b.Property(p = p.Name)
 .IsRequired()
 .HasComputedColumnSql( ((N Cnblogs +CONVERT([CHAR](8),[CreatedTime],(112)))+RIGHT(REPLICATE(N 0 ,(6))+CONVERT([NVARCHAR],[Id],(0)),(6))) );
 

在其中也有有关列名自定的方式(HasColumnName),主键是不是全自动转化成(ValueGeneratedOnAdd)等方式及其行版本号(IsRowVersion)和高并发Token(IsConcurrencyToken)。也有设定数据库索引的方式HasIndex

这儿有一个疑惑针对string默认设置设定是为NVARCHAR,其便是unicode,不知道为什么也有一个IsUnicode方式,它不也是设定为NVARCHAR的吗,它是甚么状况?求出,当我们们同时设定IsUnicode方式和列种类为VARCHAR时,则還是会转化成NVARCHAR,由此可见投射成NVARCHAR优先选择级比VARCHAR高,以下

 b.Property(p = p.Name)
 .IsRequired().IsUnicode()
 .HasColumnType( VARCHAR(21) )
 .HasComputedColumnSql( ((N Cnblogs +CONVERT([CHAR](8),[CreatedTime],(112)))+RIGHT(REPLICATE(N 0 ,(6))+CONVERT([NVARCHAR],[Id],(0)),(6))) );

小结  文中大约就略微解读了EF Core中的投射及其一些略微留意的地区,恰好今日爸爸节,在此祝福天地爸爸妈妈身心健康长命,大家下节再相见!



在线客服

关闭

客户服务热线
4008-888-888


点击这里给我发消息 在线客服

点击这里给我发消息 在线客服