ASP.NET CORE 使用 EF CORE访问数据库

asp.net core通过ef core来访问数据库,这里用的是代码优先,通过迁移来同步数据库与模型。

环境:vs2017,win10,asp.net core 2.1

一、从建立asp.net core web项目开始                                                                                

1、通过vs2017建立一个asp.net core web应用程序

分享图片

2、在models文件夹下面创建一个student类,这个类用作数据模型,表示的是数据库里面的student表 

public class Student
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public Guid ID { set; get; }
        [Required]
        [MaxLength(30)]
        public string Name { set; get; }
        public int Age { set; get; }
        public byte Sex { set; get; }
        public string Remark { set; get; }


        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public DateTime CreateDate { set; get; }
        [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
        public DateTime LastUpdate { set; get; }
    }

 关于表里面的特性说明这里暂时不管,等创建了数据库后再来说明。

3、创建数据库上下文

在项目中建立一个Data文件夹,创建一个类SqlServerContext

public class SqlServerContext : DbContext
    {
        public SqlServerContext(DbContextOptions<SqlServerContext> options)
           : base(options)
        {
        }
        public DbSet<Student> Students { get; set; }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Student>().ToTable("Student");
        }
    }

在 Entity Framework 中,实体集通常与数据表相对应,具体实体与表中的行相对应。当数据库创建完成后, EF 创建一系列数据表,表名默认和 DbSet 属性名相同。但可以在OnModelCreating方法中指定表名。

4、注册数据库上下文

打开 Startup.cs,在ConfigureServices方法中添加如下代码

services.AddDbContext<SqlServerContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("SqlServerContext")));

SqlServerContext是数据库字符串的名称。打开appsettings.json 文件,并如以下示例所示添加连接字符串。

"ConnectionStrings": {
    "SqlServerContext": "Server=(localdb)\\ProjectsV84;Database=TestDB1;Trusted_Connection=True;MultipleActiveResultSets=true"
  }

这里连接的是本地数据库,数据库的验证方式是windows验证。

5、迁移

通过命令行接口 (CLI)执行迁移命令来实现迁移,在此之前,需要按照适用于命令行接口 (CLI) 的 EF 工具。 注意: 必须通过编辑 .csproj 文件来安装此包;不能使用 install-package 命令或包管理器 GUI。

若要编辑 .csproj 文件,可右键单击解决方案资源管理器中的项目名称,然后选择“编辑EFCoreDB.csproj”,在ItemGroup里面添加如下代码

    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />

在项目所在的文件夹下打开cmd窗口,执行命令:dotnet ef migrations add CreateDB

分享图片

命令执行成功的话,会在项目中添加一个文件夹Migrations

分享图片

这里面的两个文件就是EF如何创建数据库的,一般来说不需要手动去修改这两个文件。

这时候,数据库里面还没有相应的数据库和表

在cmd中执行命令dotnet ef database update,成功执行后,就可以在数据库里面看到创建的数据库和表了

分享图片

6、分析

现在来看看student表的列和模型student的关系

分享图片

系统默认ID是主键,这是一种约定,当然也可以在模型student的ID属性上用 [Key]来修饰,这时候ID可以是其他的名称。具体有关模型创建的信息,请参考创建并配置模型

模型中,ID的类型是guid,在数据库里面就对应类型uniqueidentifier,[DatabaseGenerated(DatabaseGeneratedOption.None)]特性表示ID列不需要数据库自动添加值。

Name和Remark都是string类型,remark没有任何修饰,所以数据库中的类型就是nvarchar(max),且可以为空。

7、步骤优化

上面的的6个步骤中,第3,4两步可以不用手动添加。可以通过新搭建基架的项目命令来完成。

先完成上面的1,2两个步骤,然后在Controllers文件夹上右键==》添加==》新搭建基架的项目

分享图片

分享图片

在模型类中选择第二步添加的模型student,数据上下文类中,点击后面的+号,将名称改为sqlserver,其他的默认就行,最后点击添加。系统会自动的创建数据上下文,并且还帮你注册了,除此之外,还添加了students控制器和相应的视图,对于控制器和视图可以保留,也可以删掉。剩下的需要修改一下配置文件中数据库的连接字符串,然后接着第五步继续就可以了。

 

二、当模型修改或者添加新的模型后

1、修改模型student,添加一个学号字段code;添加模型course,每个学生可以报多个课程,每个课程可以有多个学生报名,因此student和course是多对多的关系,需要一个中间表来关联,所以添加模型Enrollment。修改后的模型如下:

 

   public class Student
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public Guid ID { set; get; }
        [Required]
        [MaxLength(30)]
        public string Name { set; get; }
        [Required]
        [MaxLength(30)]
        public string Code { set; get; }
        public int Age { set; get; }
        public byte Sex { set; get; }
        public string Remark { set; get; }
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public DateTime CreateDate { set; get; }
        [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
        public DateTime LastUpdate { set; get; }
        public ICollection<Enrollment> Enrollments { get; set; }
    }

    public class Enrollment
    {
     public int EnrollmentID { get; set; }
public int CourseID { get; set; } public Guid StudentID { get; set; } public Grade? Grade { get; set; } public Course Course { get; set; } public Student Student { get; set; } } public enum Grade { A,B,C,D,F } public class Course { [DatabaseGenerated(DatabaseGeneratedOption.None)] public int CourseID { get; set; } public string Title { get; set; } public int Credits { get; set; } public ICollection<Enrollment> Enrollments { get; set; } }

 

修改数据上下文

 public class SqlServerContext : DbContext
    {
        public SqlServerContext(DbContextOptions<SqlServerContext> options)
           : base(options)
        {
        }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Student>().ToTable("Student");
            modelBuilder.Entity<Course>().ToTable("Course");
            modelBuilder.Entity<Enrollment>().ToTable("Enrollment");

        }
        public DbSet<Student> Students { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }
        public DbSet<Course> Courses { get; set; }

    }

2、迁移

分享图片

执行这个命令后,在Migrations文件夹中添加了20190329030918_AddTable.cs文件,里面的内容就是关于模型的修改的一些代码

继续执行命令dotnet ef database update

完事后,数据库中表已经正常添加了

分享图片

分享图片

分享图片

通过上面的方式,在student表中添加了列code,新建的表Enrollment中有主键和外键。当然也可以不用设置外键,直接将表Enrollment的CourseID和StudentID设置为复合主键。这样的话,模型student中就不需要导航属性StudentID(Course,Enrollment中也是如此)。同时数据上下文中需要指定Enrollment表的复合主键:

modelBuilder.Entity<Enrollment>().ToTable("Enrollment").HasKey(c=>new { c.StudentID,c.CourseID});

这样一来,Enrollment中的EnrollmentID也要去掉。设置复合主键只能是在数据上下文中设置

三、为数据库添加初始数据

在数据库中,有些表是有初始数据的,可以通过sql语句导入,在这里通过程序来实现吧

打开Program.cs文件,修改后:

public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateWebHostBuilder(args).Build();
            using (var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                try
                {
                    var context = services.GetRequiredService<SqlServerContext>();
                    Initialize(context);
                }
                catch (Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex,"An error occurred while seeding the database.");
                }
            }


            host.Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();

        private static void Initialize(SqlServerContext context)
        {
            if (!context.Courses.Any())
            {
                var courses = new Course[]
                {
                new Course{CourseID=1050,Title="数学",Credits=3},new Course{CourseID=4022,Title="语文",new Course{CourseID=4041,Title="英语",new Course{CourseID=1045,Title="化学",Credits=4},new Course{CourseID=3141,Title="生物",new Course{CourseID=2021,Title="物理",new Course{CourseID=2042,Title="体育",Credits=4}
                };
                    foreach (Course c in courses)
                    {
                        context.Courses.Add(c);
                    }
                    context.SaveChanges();
            }

        }

    }

运行程序,数据就会添加到数据库了。

四、数据库表里面有数据的情况下修改表结构

 这里的修改肯定是合理的修改,不能说你将字符串的列改成了数字的列。这里试验一下添加新的列,不能为空的

1、在course模型中,添加一个非空的字段

分享图片

2、迁移

执行完迁移的第一个命令后,打开系统添加的文件,找到Up方法

分享图片

可以看到up方法里面只有影响修改的部分,要设置一个非空列的初始值,就需要在这里改代码了,改好了之后执行迁移的第二个命令。查询数据库,表结构已经更改,而且里面的数据也没有丢失。

 

 

 关于EF CORE的应用的基本介绍就到这里,更深入的学习还是参考微软官方文档

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


在上文中,我介绍了事件驱动型架构的一种简单的实现,并演示了一个完整的事件派发、订阅和处理的流程。这种实现太简单了,百十行代码就展示了一个基本工作原理。然而,要将这样的解决方案运用到实际生产环境,还有很长的路要走。今天,我们就研究一下在事件处理器中,对象生命周期的管理问题。事实上,不仅仅是在事件处理器
上文已经介绍了Identity Service的实现过程。今天我们继续,实现一个简单的Weather API和一个基于Ocelot的API网关。 回顾 《Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(一)》 Weather API Weather
最近我为我自己的应用开发框架Apworks设计了一套案例应用程序,并以Apache 2.0开源,开源地址是:https://github.com/daxnet/apworks-examples,目的是为了让大家更为方便地学习和使用.NET Core、最新的前端开发框架Angular,以及Apwork
HAL(Hypertext Application Language,超文本应用语言)是一种RESTful API的数据格式风格,为RESTful API的设计提供了接口规范,同时也降低了客户端与服务端接口的耦合度。很多当今流行的RESTful API开发框架,包括Spring REST,也都默认支
在前面两篇文章中,我详细介绍了基本事件系统的实现,包括事件派发和订阅、通过事件处理器执行上下文来解决对象生命周期问题,以及一个基于RabbitMQ的事件总线的实现。接下来对于事件驱动型架构的讨论,就需要结合一个实际的架构案例来进行分析。在领域驱动设计的讨论范畴,CQRS架构本身就是事件驱动的,因此,
HAL,全称为Hypertext Application Language,它是一种简单的数据格式,它能以一种简单、统一的形式,在API中引入超链接特性,使得API的可发现性(discoverable)更强,并具有自描述的特点。使用了HAL的API会更容易地被第三方开源库所调用,并且使用起来也很方便
何时使用领域驱动设计?其实当你的应用程序架构设计是面向业务的时候,你已经开始使用领域驱动设计了。领域驱动设计既不是架构风格(Architecture Style),也不是架构模式(Architecture Pattern),它也不是一种软件开发方法论,所以,是否应该使用领域驱动设计,以及什么时候使用
《在ASP.NET Core中使用Apworks快速开发数据服务》一文中,我介绍了如何使用Apworks框架的数据服务来快速构建用于查询和管理数据模型的RESTful API,通过该文的介绍,你会看到,使用Apworks框架开发数据服务是何等简单快捷,提供的功能也非常多,比如对Hypermedia的
在上一讲中,我们已经完成了一个完整的案例,在这个案例中,我们可以通过Angular单页面应用(SPA)进行登录,然后通过后端的Ocelot API网关整合IdentityServer4完成身份认证。在本讲中,我们会讨论在当前这种架构的应用程序中,如何完成用户授权。 回顾 《Angular SPA基于
Keycloak是一个功能强大的开源身份和访问管理系统,提供了一整套解决方案,包括用户认证、单点登录(SSO)、身份联合、用户注册、用户管理、角色映射、多因素认证和访问控制等。它广泛应用于企业和云服务,可以简化和统一不同应用程序和服务的安全管理,支持自托管或云部署,适用于需要安全、灵活且易于扩展的用
3月7日,微软发布了Visual Studio 2017 RTM,与之一起发布的还有.NET Core Runtime 1.1.0以及.NET Core SDK 1.0.0,尽管这些并不是最新版,但也已经从preview版本升级到了正式版。所以,在安装Visual Studio 2017时如果启用了
在上文中,我介绍了如何在Ocelot中使用自定义的中间件来修改下游服务的response body。今天,我们再扩展一下设计,让我们自己设计的中间件变得更为通用,使其能够应用在不同的Route上。比如,我们可以设计一个通用的替换response body的中间件,然后将其应用在多个Route上。 O
不少关注我博客的朋友都知道我在2009年左右开发过一个名为Apworks的企业级应用程序开发框架,旨在为分布式企业系统软件开发提供面向领域驱动(DDD)的框架级别的解决方案,并对多种系统架构风格提供支持。这个框架的开发和维护我坚持了很久,一直到2015年,我都一直在不停地重构这个项目。目前这个项目在
好吧,这个题目我也想了很久,不知道如何用最简单的几个字来概括这篇文章,原本打算取名《Angular单页面应用基于Ocelot API网关与IdentityServer4ʺSP.NET Identity实现身份认证与授权》,然而如你所见,这样的名字实在是太长了。所以,我不得不缩写“单页面应用”几个字
在前面两篇文章中,我介绍了基于IdentityServer4的一个Identity Service的实现,并且实现了一个Weather API和基于Ocelot的API网关,然后实现了通过Ocelot API网关整合Identity Service做身份认证的API请求。今天,我们进入前端开发,设计
Ocelot是ASP.NET Core下的API网关的一种实现,在微服务架构领域发挥了非常重要的作用。本文不会从整个微服务架构的角度来介绍Ocelot,而是介绍一下最近在学习过程中遇到的一个问题,以及如何使用中间件(Middleware)来解决这样的问题。 问题描述 在上文中,我介绍了一种在Angu
在大数据处理和人工智能时代,数据工厂(Data Factory)无疑是一个非常重要的大数据处理平台。市面上也有成熟的相关产品,比如Azure Data Factory,不仅功能强大,而且依托微软的云计算平台Azure,为大数据处理提供了强大的计算能力,让大数据处理变得更为稳定高效。由于工作中我的项目
在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容。下面的类图描述了我们已经实现的组件及其之间的关系,貌似系统已经变得越来越复杂了。其中绿色的部分就是上文中新实现的部分,包括一个简单的Event Store,一个事件处理器执行上下文的接
在之前《在ASP.NET Core中使用Apworks快速开发数据服务》一文的评论部分,.NET大神张善友为我提了个建议,可以使用Compile As a Service的Roslyn为语法解析提供支持。在此非常感激友哥给我的建议,也让我了解了一些Roslyn的知识。使用Roslyn的一个很大的好处
很长一段时间以来,我都在思考如何在ASP.NET Core的框架下,实现一套完整的事件驱动型架构。这个问题看上去有点大,其实主要目标是为了实现一个基于ASP.NET Core的微服务,它能够非常简单地订阅来自于某个渠道的事件消息,并对接收到的消息进行处理,于此同时,它还能够向该渠道发送事件消息,以便