EF CORE学习笔记(一) 配置Dbcontext

从Nuget下载数据库依赖

数据库对应的依赖包:

贴几个常用数据库

  • SqlServer:Microsoft.EntityFrameworkCore.SqlServer (支持 SqlServer 2005 +)

  • Sqlite:Microsoft.EntityFrameworkCore.Sqlite

  • MySql:

    • MySql.EntityFrameworkCore:支持 (MySql 8.x +)

    • Pomelo.EntityFrameworkCore.MySql:(支持 MySql 5.x +)

配置Dbcontext

​ 自己新建一个类继承Dbcontext类(需引入命名空间 Microsoft.EntityFrameworkCore)

​ 此类必须具有DbContextOptions<ApplicationDbContext> 参数的公共构造函数 例如:

public class defaultDbcontext : DbContext
{
  	 public defaultDbcontext(DbContextOptions<defaultDbcontext> options):base(options)
   {

   } 
}

配置连接字符串

​ 所有 DbContext 配置的起始点都是 DbContextOptionsBuilder可以通过三种方式获取此生成器:

  1. 在 AddDbContext 和相关方法中

    通过依赖注入在 Startup 类中的 ConfigureServices方法中 使用 AddDbContext 方法配置

    public void ConfigureServices(IServiceCollection services)
    {
          services.AddDbContext<defaultDbcontext>(optin=> {
                    optin.UseSqlite("data source=./blog.db");
                });
    }
    
  2. 在 OnConfiguring 中

    重写继承类的OnConfiguring方法

    public class defaultDbcontext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.optin.UseSqlite("data source=./blog.db");
        }
    }
    

    这些 Use*" 方法是由数据库提供程序实现的扩展方法。 这意味着必须先安装数据库提供程序 NuGet 包,然后才能使用扩展方法。

    创建并模型

    我个人理解就是根据实体生成数据库并且配置数据库各个字段(只是个人理解),说一下EFcore 是如何根据实体生成模型的具体可以参考
    https://blog.csdn.net/catshitone/article/details/116595167
    EFcore提供了两种方式生成模型 一种是 fluent API 一种是 数据注释 也就是特性 ,接下来分别演示下两种方式配置

    使用 fluent API 配置模型

    在我们刚刚创建的派生类defaultDbcontext中重写OnModelCreating方法,代码如下

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
            modelBuilder.Entity<blog>();   //blod是实体类  还可以单独配置实体的属性 例如下面这句代码
    	 //modelBuilder.Entity<blog>().Property(x=>x.img).IsRequired(); 就表示img不能为空   更多的配置方法稍后贴个表格。
    }
    

    使用数据注释方法(也叫特性)

    public class blog
    {
        public int id { get; set; }
        public string titile { get; set; }
        public string img  { get; set; }
        [Required]
        public string url { get; set; }
        public int Writerid { get; set; }
        public Writer Writer { get; set; }
    }
    

    使用特性方式要在派生类defaultDbcontext中添加公开DbSet<Blog> 类型的属性 让EFcore 知道要根据哪个实体类生成模型。贴上完整代码

    public class defaultDbcontext:DbContext
    {
        public defaultDbcontext(DbContextOptions<defaultDbcontext> options):base(options)
        {
            
        }
        public DbSet<blog> blogs;       
                     
    }
    
    public class blog
    {
        public int id { get; set; }
        public string titile { get; set; }
        public string img  { get; set; }
        [Required]
        public string url { get; set; }
        public int Writerid { get; set; }
        public Writer Writer { get; set; }
    }
    

    如果一个实体使用两种方式配置 那么fluent API会替代特性方式

    约定

    这里贴上 官方文档的说明:

    按照约定,在上下文中的 DbSet 属性中公开的类型作为实体包含在模型中。 还包括方法中指定的实体类型 OnModelCreating ,就像通过递归方式浏览其他发现的实体类型的导航属性找到的任何类型一样。

    这句话什么意思呢 看官方给出的代码

    internal class MyContext : DbContext
    {
       public DbSet<Blog> Blogs { get; set; }
    
       protected override void OnModelCreating(ModelBuilder modelBuilder)
       {
        modelBuilder.Entity<AuditEntry>();
       }
    }
    public class Blog
    {
     public int BlogId { get; set; }
     public string Url { get; set; }
    
     public List<Post> Posts { get; set; }
    }
    public class Post
    {
         public int PostId { get; set; }
         public string Title { get; set; }
         public string Content { get; set; }
     
         public Blog Blog { get; set; }
     }
    
     public class AuditEntry
     {
        public int AuditEntryId { get; set; }
        public string Username { get; set; }
        public string Action { get; set; }
     }
    

    在上面的代码中 因为实体Blod 在类型为 DbSet<Blog>的属性中所以它包含在模型中
    而实体Post是实体Blod的导航属性所在它包含在模型中
    实体AuditEntry在OnModelCreating配置所在它包含在模型中

    实体的属性约定

    • 默认会把名字为id的属性配置为主键,并且为自增长。
    • 默认情况下属性类型可为空对应的数据库列可以为null,值类型对应的列不能为null
    下面贴出常见约定
特性 应用范围 功能 FluentAPI
[NotMapped] 类或属性 在模型中排除此类或此属性的映射 modelBuilder.Ignore<BlogMetadata>();
modelBuilder.Entity<Blog>().Ignore(b => b.LoadedFromDatabase);
[Table("xxx")] 设置这个类对应的数据库表名,默认表名是DbSet<T>的属性名 modelBuilder.Entity<Blog>().ToTable("blogs");
[Table("xxx", Schema = "blogging")]* 用来设置映射的表架构,默认的架构是dbo modelBuilder.Entity<Blog>().ToTable("blogs", schema: "blogging");
[Column("xxx")] 属性 用来设置要映射的列名 modelBuilder.Entity<Blog>().Property(b => b.BlogId).HasColumnName("blog_id");
[Column(TypeName="varchar(200)")] 属性 用来设置列的数据类型
默认情况下DateTime会映射为datetime2(7),string映射到nvarchar(max)nvarchar(450)
modelBuilder.Entity<Blog>(eb =>{eb.Property(b => b.Url).HasColumnType("varchar(200)");eb.Property(b => b.Rating).HasColumnType("decimal(5, 2)");});
- - 映射到数据库视图 modelBuilder.Entity<Blog>().ToView("blogsView", schema: "blogging");
- - 映射到表值函数(TVF[) 链接
[Comment("xxxx")] 类或属性 表或列的注释 modelBuilder.Entity<Blog>().HasComment("xxxx");
modelBuilder.Entity<Blog>().Property(b => b.Url).HasComment("The URL of the blog");
[MaxLength(500)] 属性 设置最大长度,适用于数组数据类型,如stringbyte[] modelBuilder.Entity<Blog>().Property(b => b.Url).HasMaxLength(500);
- - 设置精度和小数位
通常为decimalDateTime类型的属性
modelBuilder.Entity<Blog>().Property(b => b.Score).HasPrecision(14, 2);modelBuilder.Entity<Blog>().Property(b => b.LastUpdated).HasPrecision(3);
[Required] 属性 设置列为非空
默认情况下可空类型对应的列可以为null,值类型不为null
modelBuilder.Entity<Blog>().Property(b => b.Url).IsRequired();
[Key] 属性 设置主键 modelBuilder.Entity<Car>().HasKey(c => c.LicensePlate);
1.这个特性没法应用到复合主键上,但是可以通过FluentAPI的方式:modelBuilder.Entity<Car>().HasKey(c => new { c.State, c.LicensePlate });
2.设置主键名称modelBuilder.Entity<Blog>().HasKey(b => b.BlogId).HasName("PrimaryKey_BlogId");,默认名称是PK_<type name>
[Index(nameof(Url),Name="Index_Url")]** 给实体的Url属性对应的列上设置索引,并指定索引的名称 modelBuilder.Entity<Blog>().HasIndex(b => b.Url).HasDatabaseName("Index_Url");
[Index(nameof(FirstName), nameof(LastName))] 设置复合索引 modelBuilder.Entity<Person>().HasIndex(p => new { p.FirstName, p.LastName });
[Index(nameof(Url), IsUnique = true)] 设置唯一索引 modelBuilder.Entity<Blog>().HasIndex(b => b.Url).IsUnique();
[Keyless] 设置此实体里没有主键,框架不会对此实体的状态进行跟踪,即使有更改也不会保存到数据库中 modelBuilder.Entity<Blog>().HasNoKey();
*:如果需要设置所有类的表架构,可以使用modelBuilder.HasDefaultSchema("blogging");

**:默认的索引名称是IX_<type name>_<property name>

最后说下迁移

迁移需要安装工具包Microsoft.EntityFrameworkCore.Tools安装完成后在Nuget控制台运行添加迁移命令 Add-Migration init init是迁移名称,可随意。 在运行 Update-Database init应用迁移将所做更改应用到数据库。

第一次写博客,这是我的第一篇文章,有哪些不对的地方还望各位大佬指点
上一篇:枚举当前加载的所有共享对象的所有ELF部分


下一篇:将运行Linux进程中的内存地址范围转换为目标文件中的符号?