EFCore中代码优先锲约和数据类型与数据库的对应关系

1、引言

EntityFramework Core这个我在这里就不想做相关介绍了,EFCore是netcore中才出现了,它的前身可以说是EF6,下面就对实体中定义的契约与数据库的对应做一个尝试,在实际工作中用了一段时间后现做一个整体的总结。

因为有时候只管写了实体,没有去在乎数据库中生成的结构是怎样的,开发开发着途中就会出现问题

2、需要安装的包

我这里仅对Sql Server做示例,至于Mysql、PostgreSQL、Oracle就留给读者带着同样的思路去做尝试。

1、首先需要安装的包

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.Design
  • Microsoft.EntityFrameworkCore.SqlServer
    2、配置Context
    这些都是很简单的东西,在这就做过多的解释,直接贴出代码。
  • 定义StudyDbContext
public class StudyDbContext:DbContext
{
    public StudyDbContext() { }

    public StudyDbContext(DbContextOptions<StudyDbContext> options) : base(options){}


    public DbSet<Users> Users { get; set; }
    /// <summary>
    /// 模型创建的进行时候配置
    /// </summary>
    /// <param name="modelBuilder"></param>
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}

注意:Context中又一个重载构造,实际上是在Service中添加Context的时候进行的配置

  • ConfigureServices中添加Context服务
public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    services.AddDbContext<StudyDbContext>(builder => builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}

附上连接字符串:

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Database=TestEfCore;Trusted_Connection=True;"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

这里的配置还有很多其他的,参见定义,后面再做其他配置的介绍。
在这里插入图片描述

3、锲约与数据库的对应关系

下面步入今天的正题

public class Users
{
    [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public int Age { get; set; }

    [MaxLength(12)]
    public string Name { get; set; }

    public Gender Gender { get; set; }

    [DataType(DataType.DateTime)]
    public DateTime CreationTime { get; set; }

}
public enum Gender
{
    UnKnow,
    Male,
    Female,        
}

这里定义一个简单的用户,通过上面定义后再加入到Context中去,上面已经贴出了DbSet<Uers>

3.1、添加模型更改

Add-Migration <说明>
使用dotnet  ef migration add <说明>  也是可以的

这时候项目会自动编译,要是出现编译不成功的时候是添加不了的。
在这里插入图片描述

说明:这里出现了一个警告是因为我安装的包是3.1.3的,而EF Core tools是使用的3.1.2。避免此错误 也是可以将Microsoft.EntityFrameworkCore.Tools 3.1.3添加到项目中去

3.2、更新数据库

当添加完成后会自动生成对应的Mirations文件
在这里插入图片描述
这里关于文件里面的内容在此文章中就不在多啰嗦了,后面有需要时我会详细介绍。

使用命令更新数据库

update-database
使用dotnet  ef migration database update  也是可以的

在这里插入图片描述
这样就生成了数据库了
在这里插入图片描述
到了这里差不多算是EF Core代码优先整个流程就完成了,其实在实际开发中肯定是单独剥离到仓储里面去单独创建MigrationEntityFrameworkCore层。

有时候可能需要对应的sql脚本文件,可以使用Script-Migration生成一个随机命名的sql文件

Script-Migration
使用dotnet  ef migrations script  也是可以的

生成的结果。
在这里插入图片描述

3.3、对比

善于观察的童鞋们肯定已经看出了某些对比关系。

契约 数据库 说明
[Table(“Users”)] 数据库表名为Users 不指定名称默认为类名称,包括属性一样
[Key] 主键
[ForeignKey(“FK_XXX_XXX”)] 外键 实际开发中我基本上没有定义外键,通过导航属性会自动识别外键
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] 自增 DatabaseGeneratedOptions说明,None-既不自增也不计算;Identity-自增;Computed-通过计算得到值(这个后面进行讲解)
[MaxLength(12)] nvarchar(12) 通过设定length数据库自动建立最大长度约束
[StringLength(200)] nvarchar(200) 通过设定maximumLength数据库自动建立长度约束
[Column(TypeName=“datetime”)] datetime 指定数据库类型
[Column(“Love”)] 数据库列明为Love
[NotMapped] 不映射到数据库
后面再对这里的契约进行补充说明,这些都是我平时用到的。
数据类型 数据库类型 说明
枚举 int 当没有设定可空类型的时候数据库中是非空。值类型默认都是非空,要是希望可为空可以使用 ?语法糖或者Nullable
bool bit mssql中bit其实就是bool类型
decimal decimal(18,2) decimal类型在生成的时候会有警告;(No type was specified for the decimal column ‘Udecimal’ on entity type ‘Users’. This will cause values to be silently truncated if they do not fit in the default precision and scale. Explicitly specify the SQL server column type that can accommodate all the values using ‘HasColumnType()’)。意思就是说没有指定精度会默认采用精度截取,但是可以采用[Column(TypeName = “decimal(18,4)”)]来结局,这样会用到很多地方,但是这样存在硬编码始终不爽,至于怎么处理读者自行解决
string nvarchar(MAX)
int int
double float
float real
uint bigint
long bigint
ulong decimal(20)
Int16 int
Int32 bigint
Int64 bigint
UInt16 int
UInt32 bigint
UInt64 decimal(20)
dynamic 报错 这个类型有过了解的童鞋们应该就知道为什么会报错了,错误 信息:(The property ‘Users.Udynamic’ could not be mapped, because it is of type ‘object’ which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the ‘[NotMapped]’ attribute or by using ‘EntityTypeBuilder.Ignore’ in ‘OnModelCreating’)
肯定还有很多类型的对应,我这里主要写平时中常用的 数据类型

这边文章中就对这么几个做一个简单的介绍,后面详细的做其他讲解,由于最近大多数都在讨论EF Core各种问题,我也就在这针对我实际开发中用到的做一个讲解,希望能够给还不会不明白的带来帮助。

3.4、Users代码与表结构

Users表,这里贴出来是便于童鞋们可以自行测试一下。

public class Users
    {
        [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public int Age { get; set; }
        [MaxLength(12)]
        public string Name { get; set; }
        public Gender Gender { get; set; }
        public bool IsActive { get; set; }
        [DataType(DataType.DateTime)]
        public DateTime CreationTime { get; set; }
        public double Udouble { get; set; }
        public float Ufloat { get; set; }
        public decimal Udecimal { get; set; }
        public uint Uuint { get; set; }
        public long Ulong { get; set; }
        public ulong Uulong { get; set; }
        public Int16 UInt16 { get; set; }
        public Int32 UInt32 { get; set; }
        public Int64 UInt64 { get; set; }
        public UInt16 UuInt16 { get; set; }
        public UInt32 UuInt32 { get; set; }
        public UInt64 UuInt64 { get; set; }      
        public byte Ubyte { get; set; }        
        public char Uchar { get; set; }
    }
    public enum Gender
    {
        UnKnow,
        Male,
        Female,        
    }

表结构展示
在这里插入图片描述

4、总结

本篇文章就逼逼奈奈到这 ,有那点不正确的地方希望能够指出来,写文章有时候还真是 停费事,能够帮助到某些童鞋的话还是有那么一丝欣慰感 ,关注我持续更新相关实战经验。

posted @ 2020-04-02 21:44  Jonny-Xhl  阅读(547)  评论(0编辑  收藏  举报