HTML5技术

EntityFramework Core映射关系详解 - Jeffcky(3)

字号+ 作者:H5之家 来源:H5之家 2017-06-19 17:01 我要评论( )

public class BookMap : EntityMappingConfigurationBook { Map(EntityTypeBuilderBook b){b.ToTable( );b.HasKey(k = k.Id);b.HasAlternateKey(k = k.UserId);}} 最后监控得到如下语句: 看到没,为用户Id配置了唯

public class BookMap : EntityMappingConfiguration<Book> { Map(EntityTypeBuilder<Book> b) { b.ToTable(); b.HasKey(k => k.Id); b.HasAlternateKey(k => k.UserId); } }

最后监控得到如下语句:

看到没,为用户Id配置了唯一约束:

CONSTRAINT [AK_Book_UserId] UNIQUE ([UserId])

所以我们得出结论:通过可选键我们可以创建唯一约束来除主键之外唯一标识行。

主体键映射(Principal Key) 

如果我们想要一个外键引用一个属性而不是主键,此时我们可以通过主体键映射来进行配置,此时配置主体键映射背后实际上自动将其设置为一个可选键。这个就不用我们多讲了。

好了到此为止我们讲完了键映射,接下来我们再来讲述属性映射:

属性映射

对于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() .HasMaxLength(50);

通过上述迁移出错,我们修改成如下才正确:

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

解决一个,又来一个,那么对于枚举类型我们又该进行如何映射呢,枚举对应数据库中的类型为TINYINT,我们进行如下设置:

public class Product { public int Id { get; set; } public string Name { get; set; } public Type Type { get; set; } public IEnumerable<ProductCategory> ProductCategorys { get; set; } } public enum Type { [Description()] General = 0, [Description()] Insurance = 1 }

public class ProductMap : EntityMappingConfiguration<Product> { Map(EntityTypeBuilder<Product> b) { b.ToTable(); b.HasKey(k => k.Id); b.Property(p => p.Type) .IsRequired() .HasColumnType("TINYINT"); } }

此时则对应生成我们想要的类型:

CREATE TABLE [Product] ( [Id] int NOT NULL IDENTITY, [Name] nvarchar(max), [Type] TINYINT NOT NULL, CONSTRAINT [PK_Product] PRIMARY KEY ([Id])

【注意】:此时将其映射成枚举没毛病上述已经演示,但是当我们获取数据时将TINYINT转换成枚举时将出现如下错误:

说到底TINYINT对应C#中的byte类最后尝试将其转换为int才会导致转换失败,所以在定义枚举时记得将其继承自byte,如下才好使:

public enum Type : byte { [Description()] General = 0, [Description()] Insurance = 1 }

讲完如上映射后,我们再来讲讲默认值映射。 当我们敲默认映射会发现有两个,一个是HasDefaultValue,一个是HasDefaultValueSql,我们一起来看看到底如何用:

我们在Product类中添加Count字段:

public int Count { get; set; }

b.Property(p => p.Count).HasDefaultValue(0);

如上是对于int类型如上设置,如果是枚举类型呢,我们来试试:

b.Property(p => p.Type) .IsRequired() .HasColumnType().HasDefaultValue(0);

此时迁移将出现如下错误:

也就是说无法将枚举值设置成int类型,此时我们应该利用HasDefaultValueSql来映射:

b.Property(p => p.Type) .IsRequired() .HasColumnType().HasDefaultValueSql();

对于默认值映射总结起来就一句话:对于C#中的类型和数据库类型一致的话用HasDefaultValue,否则请用HasDefaluValueSql。

【注意】:对于字段类型映射有一个奇葩特例,对于日期类型DateTime,在数据库中也存在其对应的类型datetime,但是如果我们不手动指定类型会默认映射成更精确的日期类型即datetime2(7)。

我们在Product类中添加创建时间列,如下:

public DateTime CreatedTime { get; set; }

此时我们不指定其映射类型,此时我们看到在数据库中的类型为datetime2(7)

当然以上映射也没什么问题,但是对于大部分对于日期类型都是映射成datetime且给定默认时间为当前时间,所以此时需要手动进行配置,如下:

b.Property(p => p.CreatedTime) .HasColumnType() .HasDefaultValueSql();

说完默认值需要注意的问题,我们再来讲讲计算列的映射,在EF Core中对于计算列映射,在之前版本为ForSqlServerHasComputedColumnSql,目前是HasComputedColumnSql。例如如下这是计算列:

b.Property(p => p.Name) .IsRequired() .HasComputedColumnSql();

 

其中还有关于列名自定义的方法(HasColumnName),主键是否自动生成(ValueGeneratedOnAdd)等方法以及行版本(IsRowVersion)和并发Token(IsConcurrencyToken)。还有设置索引的方法HasIndex

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 在.NET Core中使用Irony实现自己的查询语言语法解析器 - dax.net

    在.NET Core中使用Irony实现自己的查询语言语法解析器 - dax.net

    2017-06-07 18:00

  • Amazing ASP.NET Core 2.0 - Savorboard

    Amazing ASP.NET Core 2.0 - Savorboard

    2017-05-25 14:00

  • Linux使用Jexus托管Asp.Net Core应用程序 - 玩双截棍的熊猫

    Linux使用Jexus托管Asp.Net Core应用程序 - 玩双截棍的熊猫

    2017-05-15 08:06

  • ASP.NET Core:部署项目到Ubuntu Server - 王杰光

    ASP.NET Core:部署项目到Ubuntu Server - 王杰光

    2017-05-07 18:01

网友点评
<