一起学ASP.NET Core 2.0学习笔记(二): ef core2.0 及mysql provider 、Fluent API相关配置及迁移

不得不说微软的技术迭代还是很快的,上了微软的船就得跟着她走下去,前文一起学ASP.NET Core 2.0学习笔记(一): CentOS下 .net core2 sdk nginx、supervisor、mysql环境搭建搭建好了.net core linux的相关环境,今天就来说说ef core相关的配置及迁移:

简介:

Entity Framework(以下简称EF) 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案,EF Core是Entity framework得下一版本,相比EF原来版本(4-6.1),显得更加轻量级,相比同样出身名门的dapper还是显得有点庞大,不过鱼与熊掌向来不可兼得,想想一堆堆语法糖,方便的linq查询以及lambda表达式,可以很大程度上从T-SQL语法上脱身出来很多,在配置过程中也碰到一些问题,记录下来,以便后期翻阅:

一.poco的创建以及Fluent Api关系配置

1.一对多关系:

项目中最常见的就是一对多关系了,以语言及语言为例

语言(Language)类

 1 public partial class Language : BaseEntity<int>
 2     {
 3         private ICollection<LocaleStringResource> _localeStringResources;
 4
 5         /// <summary>
 6         /// Gets or sets the name
 7         /// </summary>
 8
 9         public string Name { get; set; }
10
11         /// <summary>
12         /// Gets or sets the language culture
13         /// </summary>
14
15         public string LanguageCulture { get; set; }
16
17         /// <summary>
18         /// Gets or sets the unique SEO code
19         /// </summary>
20
21         public string UniqueSeoCode { get; set; }
22
23         /// <summary>
24         /// Gets or sets the flag image file name
25         /// </summary>
26
27         public string FlagImageFileName { get; set; }
28
29         /// <summary>
30         /// Gets or sets a value indicating whether the language supports "Right-to-left"
31         /// </summary>
32
33         public bool Rtl { get; set; }
34
35
36         /// <summary>
37         /// Gets or sets a value indicating whether the language is published
38         /// </summary>
39
40         public bool Published { get; set; }
41
42         /// <summary>
43         /// Gets or sets the display order
44         /// </summary>
45
46         public int DisplayOrder { get; set; }
47
48         public bool IsDefault { get; set; }
49
50         /// <summary>
51         /// Gets or sets locale string resources
52         /// </summary>
53         public virtual ICollection<LocaleStringResource> LocaleStringResources
54         {
55             get { return _localeStringResources ?? (_localeStringResources = new HashSet<LocaleStringResource>()); }
56             protected set { _localeStringResources = value; }
57         }

语言资源(LocaleStringResource):

 1 public partial class LocaleStringResource : BaseEntity<int>
 2     {
 3         /// <summary>
 4         /// Gets or sets the language identifier
 5         /// </summary>
 6         public int LanguageId { get; set; }
 7
 8         /// <summary>
 9         /// Gets or sets the resource name
10         /// </summary>
11         public string ResourceName { get; set; }
12
13         /// <summary>
14         /// Gets or sets the resource value
15         /// </summary>
16         public string ResourceValue { get; set; }
17
18         /// <summary>
19         /// Gets or sets a value indicating whether this resource was installed by a plugin
20         /// </summary>
21         public bool? IsFromPlugin { get; set; }
22
23         /// <summary>
24         /// Gets or sets a value indicating whether this resource was modified by the user
25         /// </summary>
26         public bool? IsTouched { get; set; }
27
28         /// <summary>
29         /// Gets or sets the language
30         /// </summary>
31         public virtual Language Language { get; set; }
32
33     }

其中语言及资源主外键关系配置如下

 1  public partial class LanguageMapper : IEntityTypeConfiguration<Language>
 2     {
 3         public void Configure(EntityTypeBuilder<Language> builder)
 4         {
 5             builder.ToTable("Language");
 6             builder.HasKey(r => r.Id);
 7             builder.HasIndex(r => r.LanguageCulture);
 8             builder.HasIndex(r => r.Name);
 9             builder.HasIndex(r => r.UniqueSeoCode);
10         }
11     }

 public partial class LocaleStringResourceMapper : IEntityTypeConfiguration<LocaleStringResource>
    {
        public void Configure(EntityTypeBuilder<LocaleStringResource> builder)
        {
            builder.ToTable("LocaleStringResource");
            builder.HasKey(r => r.Id);
            builder.HasIndex(r => r.LanguageId);
            builder.HasIndex(r => r.ResourceName);
            builder.HasOne(r => r.Language).WithMany(b => b.LocaleStringResources)
                .HasForeignKey(fk => fk.LanguageId);
        }
    }

2、父子关系 :

 1  public class TechCategory:BaseEntity<int>
 2     {
 3         /// <summary>
 4         /// 名称
 5         /// </summary>
 6         public string Name { get; set; }
 7         /// <summary>
 8         /// 分类描述
 9         /// </summary>
10         public string Descript { get; set; }
11         /// <summary>
12         /// meta标题
13         /// </summary>
14         public string MetaTitle { get; set; }
15         /// <summary>
16         /// meta描述
17         /// </summary>
18         public string MetaDescript { get; set; }
19         /// <summary>
20         /// 缩略图
21         /// </summary>
22         public string Thumb { get; set; }
23         /// <summary>
24         /// 图片
25         /// </summary>
26         public string Image { get; set; }
27         /// <summary>
28         /// 排序
29         /// </summary>
30         public int Sort { get; set; }
31         /// <summary>
32         /// 父级分类
33         /// </summary>
34         public int? ParentId { get; set; }
35
36         /// <summary>
37         /// 父级分类
38         /// </summary>
39
40         public virtual TechCategory Parent { get; set; }
41         public virtual ICollection<Technology> Technologys { get; set; }
42         /// <summary>
43         /// 子级
44         /// </summary>
45         public virtual ICollection<TechCategory> Childs { get; set; }
46         /// <summary>
47         /// 关键词
48         /// </summary>
49         public string Slug { get; set; }
50         /// <summary>
51         /// 创建时间
52         /// </summary>
53         public long CreatedOn { get; set; }
54     }

 1  public class TechCategoryMapper : IEntityTypeConfiguration<TechCategory>
 2     {
 3         public void Configure(EntityTypeBuilder<TechCategory> builder)
 4         {
 5             builder.ToTable("TechCategory");
 6             builder.HasKey(r => r.Id);
 7             builder.HasMany(r => r.Childs).WithOne(x => x.Parent)
 8              .HasForeignKey(fk => fk.ParentId);
 9             builder.HasIndex(r => r.Name);
10         }
11     }

二、数据库上下文:

根据前面创建的相关实体类 以及相关mapper类型,我们可以重现DbContext的OnModelCreating的方法,反射出实现了IEntityTypeConfiguration接口的相关mapper类型创建相关实体-数据表的相关对应关系

 1  public class DefaultContext : DbContext
 2     {
 3         public DefaultContext(DbContextOptions<DefaultContext> opt)
 4             :base(opt)
 5         {
 6             AutoCommitEnabled = true;
 7         }
 8   protected override void OnModelCreating(ModelBuilder builder)
 9         {
10             base.OnModelCreating(builder);
11             var mappingInterface = typeof(IEntityTypeConfiguration<>);
12             // Types that do entity mapping
13             var mappingTypes = GetType().GetTypeInfo().Assembly.GetTypes()
14                 .Where(x => x.GetInterfaces().Any(y => y.GetTypeInfo().IsGenericType && y.GetGenericTypeDefinition() == mappingInterface));
15
16             // Get the generic Entity method of the ModelBuilder type
17             var entityMethod = typeof(ModelBuilder).GetMethods()
18                 .Single(x => x.Name == "Entity" &&
19                         x.IsGenericMethod &&
20                         x.ReturnType.Name == "EntityTypeBuilder`1");
21
22             foreach (var mappingType in mappingTypes)
23             {
24
25                 // Get the type of entity to be mapped
26                 var genericTypeArg = mappingType.GetInterfaces().Single().GenericTypeArguments.Single();
27
28                 // Get the method builder.Entity<TEntity>
29                 var genericEntityMethod = entityMethod.MakeGenericMethod(genericTypeArg);
30
31                 // Invoke builder.Entity<TEntity> to get a builder for the entity to be mapped
32                 var entityBuilder = genericEntityMethod.Invoke(builder, null);
33
34                 // Create the mapping type and do the mapping
35                 var mapper = Activator.CreateInstance(mappingType);
36                 mapper.GetType().GetMethod("Configure").Invoke(mapper, new[] { entityBuilder });
37             }
38             foreach (var relationship in builder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
39             {
40                 relationship.DeleteBehavior = DeleteBehavior.Restrict;
41             }
42         }
43     }

三、多数据库支持:

多数据库的支持,并不是意味着同时对多种数据库操作,当然,后面,我们会尝试同时对多种数据库操作,这可能需要多个上下文,暂且不论。分布式数据库。我们的项目可能是在windows上开发的使用的是SqlServer,我们要发布到linux上,SqlServer 2017 据说是支持liunx的,但是还没出... 当然不是说 SqlServer 就不能装在liunx上,但是我们的Liunx服务器可能已经安装了MySql或 Oracle,我们希望使用现有的,又或者是,我们需要切换数据库。那么,我们需要可以随时切换数据库的支持,以上篇的mysql为例:

1.引用相关包,mysql我用的Pomelo.EntityFrameworkCore.MySql,国人开发的mysql for ef core的相关服务对象,ef

core 2.0中需要指定2.0版本(Install-Package Pomelo.EntityFrameworkCore.MySql -Version 2.0.0-rtm-10059),

2.需改配置文件依据相关配置动态加载数据库提供对象;相关代码及配置如下

nuget引用列表

1  <ItemGroup>
2     <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.0" />
3     <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0" />
4     <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" />
5     <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.0.0-rtm-10058" />
6   </ItemGroup>

相关配置文件修改

 "ConnectionStrings": {
    "MongoDbConnectionString": "mongodb://tchistory:[email protected]/history",
    "ConnectionString": "Data Source=127.0.0.1;Initial Catalog=farmdata;User ID=root;Password=123456",
    "DataProvider": "MySql"
  },

在startup.cs 的configureServices方法中添加数据库上下文

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<DefaultContext>(option => option.UseFarmDatabase(Configuration));
            services.UseFarmService(Configuration);
            services.AddMvc();

        }

数据库提供对象扩展方法如下:

public static DbContextOptionsBuilder UseFarmDatabase(this DbContextOptionsBuilder optionsBuilder, IConfiguration configuration)
{
string provider = configuration.GetConnectionString("DataProvider"), connection = configuration.GetConnectionString("ConnectionString");
if (provider.Equals(DataBaseServer.SqlServer, StringComparison.InvariantCultureIgnoreCase))
{
return optionsBuilder.UseSqlServer(connection);
}
else if (provider.Equals(DataBaseServer.MySql, StringComparison.InvariantCultureIgnoreCase))
{
return optionsBuilder.UseMySql(connection);
}
else
{
throw Error.Argument("UseDatabaseServer", "No databaseProvider");
}
}

在程序包管理控制台添加相关迁移 命令 add-migration init:  会在当前目录下生成相关迁移目录

执行update-database -Verbose提交更改到数据库,这样数据库迁移及更改就算完成了,其中要注意的地方是ef core 2.0 中有些数据库提供对象暂时是没有完全实现,如用Pomelo.EntityFrameworkCore.MySql -Version 1.1.2 可能会报方法未实现,更新2.0 rtm版本即可。

祝愿你在码农道路上越走越顺畅;

时间: 2024-10-04 15:28:10

一起学ASP.NET Core 2.0学习笔记(二): ef core2.0 及mysql provider 、Fluent API相关配置及迁移的相关文章

一起学ASP.NET Core 2.0学习笔记(一): CentOS下 .net core2 sdk nginx、supervisor、mysql环境搭建

作为.neter,看到.net core 2.0的正式发布,心里是有点小激动的,迫不及待的体验了一把,发现速度确实是快了很多,其中也遇到一些小问题,所以整理了一些学习笔记: 阅读目录 环境说明 安装CentOS7 安装.NET Core SDK for CentOS7 搭建ftp服务器 安装mysql 部署ASP.NET Core应用程序 配置Nginx 配置守护服务(Supervisor) 环境说明 服务器系统:CentOS 7.3 64位 相关工具:putty.Xftp 服务器软件软件:.n

从零开始学 ASP.NET Core 与 EntityFramework Core 目录

从零开始学 ASP.NET Core 与 EntityFramework Core 介绍 我是一个目录,它旨在帮助开发者循序渐进的了解 ASP.NET Core 和 Entity Framework Core . 文章会随着版本进行更新,关注我获取最新版本 目标 我们将详细讨论和学习: .NET 平台 ASP.NET Core ASP.NET Core MVC ASP.NET Identity Core Entity Framework Core 适用对象 学习本书的前置条件只需要你有一点 C#

ASP.NET Core on K8S学习初探(1)K8S单节点环境搭建

当近期的一个App上线后,发现目前的docker实例(应用服务BFF+中台服务+工具服务)已经很多了,而我司目前没有专业的运维人员,发现运维的成本逐渐开始上来,所以容器编排也就需要提上议程.因此我决定开始学习Kubernetes,会将学习当中的过程记录下来,预计会形成一个系列,暂且命名为:ASP.NET Core on K8S,而这个系列会由3个部分组成,且会在不同的时期写完: ASP.NET Core on K8S学习初探:在Docker for Windows中搭建单节点环境,初步了解有个感

微软企业库5.0学习笔记(10)ASP.NET模块依赖注入

您可以使用HTTP模块,一个到ASP.NET HttpApplicationState类的扩展,在Global.asax编写代码强制ASP.NET在每一个页面请求时自动注入依赖的对象,就像在ASP.NET Web窗体应用程序中讨论的一样. 下列方法显示了一个合适的方法能够获取PreRequestHandlerExecute事件将它自己注入到ASP.NET的执行流水线,在每个页面请求中通过容器的BuildUp方法运行Http模块,并获取OnPageInitComplete事件.当OnPageIni

ASP.NET Core 源码学习之 Logging

在ASP.NET 4.X中,我们通常使用 log4net, NLog 等来记录日志,但是当我们引用的一些第三方类库使用不同的日志框架时,就比较混乱了.而在 ASP.Net Core 中内置了日志系统,并提供了一个统一的日志接口,ASP.Net Core 系统以及其它第三方类库等都使用这个日志接口来记录日志,而不关注日志的具体实现,这样便可以在我们的应用程序中进行统一的配置,并能很好的与第三方日志框架集成. 注册日志服务 ASP.NET Core 全部使用依赖注入,更好的规范我们的代码.想要使用日

ASP.Net MVC开发基础学习笔记(3):Razor视图引擎、控制器与路由机制学习

首页 头条 文章 频道                         设计频道 Web前端 Python开发 Java技术 Android应用 iOS应用 资源 小组 相亲 频道 首页 头条 文章 小组 相亲 资源 设计 前端 Python Java 安卓 iOS 登录 注册 首页 最新文章 经典回顾 开发 Web前端 Python Android iOS Java C/C++ PHP .NET Ruby Go 设计 UI设计 网页设计 交互设计 用户体验 设计教程 设计职场 极客 IT技术

ASP.Net MVC开发基础学习笔记:三、Razor视图引擎、控制器与路由机制学习

一.天降神器“剃须刀” — Razor视图引擎 1.1 千呼万唤始出来的MVC3.0 在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor.在这之前,我们一直在使用WebForm时代沿留下来的ASPX引擎或者第三方的NVelocity模板引擎. Razor在减少代码冗余.增强代码可读性和Visual Studio智能感知方面,都有着突出的优势.Razor一经推出就深受广大ASP.Net开发者的喜爱. 1.2 Razor的语法 (1)Razor文件类型:Razor支持两种文件类型,分

ASP.Net开发基础温故知新学习笔记

申明:本文是学习2014版ASP.Net视频教程的学习笔记,仅供本人复习之用,也没有发布到博客园首页. 一.一般处理程序基础 (1)表单提交注意点: ①GET通过URL,POST通过报文体: ②需在HTML中为表单元素设置name: ③元素id是给Dom用的,name才是提交给服务器用的: (2)请求处理响应模型: ①浏览器发出访问请求→②服务器处理访问请求并返回HTML→③浏览器解析HTML并显示页面 (3)GET与POST的区别:(★★★→重点) ①GET通过URL传值,而POST通过HTT

Quartz.NET 2.0 学习笔记(1) :Quartz.NET简介

转自:http://www.cnblogs.com/lzrabbit/archive/2012/04/13/2447609.html Quartz.NET 项目地址 http://quartznet.sourceforge.net/ Quartz.NET 2.0 学习笔记(1) :Quartz.NET简介 Quartz.NET 2.0 学习笔记(2) :和1.0的几点不同 Quartz.NET 2.0 学习笔记(3) :通过配置文件实现任务调度 Quartz.NET 2.0 学习笔记(4) :c