一起学ASP.NET Core 2.0学习笔记(二)- ef core2.0 及mysql provider 、Fluent API相关配置及迁移
来源:互联网 发布:如何去除马赛克软件 编辑:程序博客网 时间:2024/06/05 08:07
不得不说微软的技术迭代还是很快的,上了微软的船就得跟着她走下去,前文一起学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 culture13 /// </summary>14 15 public string LanguageCulture { get; set; }16 17 /// <summary>18 /// Gets or sets the unique SEO code19 /// </summary>20 21 public string UniqueSeoCode { get; set; }22 23 /// <summary>24 /// Gets or sets the flag image file name25 /// </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 published38 /// </summary>39 40 public bool Published { get; set; }41 42 /// <summary>43 /// Gets or sets the display order44 /// </summary>45 46 public int DisplayOrder { get; set; }47 48 public bool IsDefault { get; set; }49 50 /// <summary>51 /// Gets or sets locale string resources52 /// </summary>53 public virtual ICollection<LocaleStringResource> LocaleStringResources54 {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 name10 /// </summary>11 public string ResourceName { get; set; }12 13 /// <summary>14 /// Gets or sets the resource value15 /// </summary>16 public string ResourceValue { get; set; }17 18 /// <summary>19 /// Gets or sets a value indicating whether this resource was installed by a plugin20 /// </summary>21 public bool? IsFromPlugin { get; set; }22 23 /// <summary>24 /// Gets or sets a value indicating whether this resource was modified by the user25 /// </summary>26 public bool? IsTouched { get; set; }27 28 /// <summary>29 /// Gets or sets the language30 /// </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 mapping13 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 type17 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 mapped26 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 mapped32 var entityBuilder = genericEntityMethod.Invoke(builder, null);33 34 // Create the mapping type and do the mapping35 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:tc123456@127.0.0.1/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版本即可。
祝愿你在码农道路上越走越顺畅;
- 一起学ASP.NET Core 2.0学习笔记(二)- ef core2.0 及mysql provider 、Fluent API相关配置及迁移
- 一起学ASP.NET Core 2.0学习笔记(一)- CentOS下 .net core2 sdk nginx、supervisor、mysql环境搭建
- 一步步学习EF Core(3.EF Core2.0路线图)
- EF CodeFirst 约定、注释及Fluent API
- MySql 使用 EF Core 2.0 CodeFirst、DbFirst、数据库迁移(Migration)介绍及示例
- 一步一步带你做WebApi迁移ASP.NET Core2.0
- EF Code First 学习笔记:约定配置Data Annotations+Fluent API
- 从头编写 asp.net core 2.0 web api 基础框架 (4) EF配置
- 实现自己的.NET Core配置Provider之EF
- 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(二)-- Web Api Demo
- .NET Core2.0 MVC中使用EF访问数据
- 从头编写 asp.net core 2.0 web api 基础框架 (5) EF CRUD
- Asp.NET 第一课 笔记及相关
- ORM系列之二:EF(3) 约定、注释、Fluent API
- .net framework 迁移至.net core2.0专题
- ASP.NET Core 缓存技术 及 Nginx 缓存配置
- .net core 2.0学习笔记(三):度量.net framework 迁移到.net core的工作量
- .net core 2.0学习笔记(四):迁移.net framework 工程到.net core
- 优化SQL查询:如何写出高性能SQL语句
- 网络爬虫系列笔记(2)——Requests库
- Scala Annotation (注解)
- Java发邮件基础篇
- R语言的科学编程与仿真-第二章答案
- 一起学ASP.NET Core 2.0学习笔记(二)- ef core2.0 及mysql provider 、Fluent API相关配置及迁移
- 1008. 数组元素循环右移问题 (20)用时18min得分20
- 中小型企业网的实现
- 解决Android Studio的Instant Run导致的错误
- UVA11624 Fire!【BFS+细心】
- 常见的web服务器软件分类
- <android> 智能家居 物联网 声纹开锁
- Unity LeanTouch 笔记
- haha