前言
哇。。看看时间 真的很久很久没写博客了 将近一年了。
最近一直在忙各种家中事务和公司的新框架 终于抽出时间来更新一波了。
本篇主要讲一下关于Entity Framework Core访问oracle数据库的采坑。。
强调一下,本篇文章发布之前 关于Entity Framework Core访问oracle数据库的甲骨文官方dll还未正式发布。
不过我已经在项目中用起来了。。介意的兄弟可以先等等。。甲骨文说的是本年第三季度。。
环境
首先我们来看看所谓的官方支持吧。
操作系统:
.NET版本:
1.NET Core 2.1 或者更高
2.NET Framework 4.6.1 或者更高
· Entity Framework Core版本:
1. 2.1版本或者更高
依赖库:
1. ODP.NET Core 18.3或者更高 2.Microsoft.EntityFrameworkCore.Relational 2.1或者更高 3.Access to Oracle Database 11g Release 2 (11.2) 或者更高
正文
本篇将采取CodeFirst的形式来创建数据库。。
我们创建上下文与实体如下:
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseOracle(@"SQL Contion", b => b.UseOracleSQLCompatibility("11"));
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
//public int Rating { 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 int BlogId { get; set; }
public Blog Blog { get; set; }
}
这里我们先介绍第一个要注意的地方,UseOracle参数里面跟的UseOracleSQLCompatibility方法,里面参数传递的11,指的是oracle11g版本。如果你是12g版本 请传递12.
因为11g和12g的SQL语法有较多不同的地方,所以用这个来区分。
然后我们add一个版本 执行nuget命令如下:(PS:不懂如何使用codeFirst的请移步:Entity Framework Core 之数据库迁移)
Add-Migration BanBen1
然后将版本更新到数据库如下:
Update-Database
数据库生成成功。
我们这时候编写插入语句如下:
using (BloggingContext db = new BloggingContext())
{
db.Blogs.Add(new Blog { Url = "aaaaa1" });
db.SaveChanges();
}
看似没问题的语句,会得到一个错误消息如下:
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
这是因为我们没有给主键赋值导致的错误信息。(因为oracle没有自增主键,只能通过序列自增)
那么自增序列如何使用呢?
我们查看数据库会发现,如图:
codefirst已经帮我们生成了序列,但是并不会自动使用。我们需要配置一下:
在上下文中的OnModelCreating方法添加如下代码:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>(entity =>
{
entity.ToTable("Posts");
entity.Property(o => o.PostId).ForOracleUseSequenceHiLo("Posts_PostId_sq3");
});
modelBuilder.Entity<Blog>(entity =>
{
entity.ToTable("Blogs");
entity.Property(o => o.BlogId).ForOracleUseSequenceHiLo("Blogs_BlogId_sq1");
});
}
指定对应表的序列。
然后在运行。即可添加成功了。
在我的生产项目中。应该是打包到docker直接运行部署的。
不过在打包到docker的过程中又出现了诡异的问题。
就不重现了。。反正就是开发环境没有问题。。直接放到linux中也没问题。但是一旦打包到docker运行 就会查询不到数据。
经过多方查证 最终发现是微软提供的rumtime镜像,因为是精简版系统 所以里面的市区有问题。
在dockerfile中添加如下语句 在生成的时候 设置好时区:
FROM microsoft/dotnet:2.1-aspnetcore-runtime
ENV TZ=Asia/Shanghai
这样就能成功的操作到数据库了。。
结束语
近期移植了好些个项目到.NET CORE 或多或少遇到了不少坑。。应该算是采坑无数了。。
其实大部分都集中在数据库连接这一块。。比如oracle DB2 。。(PS:感觉也就mysql与sql server支持是最好的。。)
DB2虽然官方发布了。但是他的坑其实比oracle还大。。我们下篇在写。。