业务场景
- 俩个数据库之间的数据需要迁移,然后表的结构不同,且迁移过程中还涉及到一丢丢数据的加工处理,因此不能简单的使用导入导入,然后列映射的功能完成任务了
- .net core的nuget包,刚好有对应数据库的驱动,另外刚开始,是不想写实体类的,指望着使用DBFirst模式生成代码(EF Core里面,好像已经不叫DB First了)
- 后来,从数据库表生成代码失败了。。。所以选择手写实体类来映射数据库表
技术实现
虚空代码
- 引入需要的nuget包
- 创建实体类
- 创建EF的上下文,并且把实体类对应的数据集属性DBSet手动填上
- 控制台项目启动,创建不同的数据库上下文,开始处理数据
实际开发
-
需要引入的包,不仅EF Core所在的项目需要,解决方案的启动项目也需要
-
创建实体类,注意对应的几个特性需要加上(Table, Key, Columns, MaxLength)
-
using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; [Table("T_CARGO")] public class T_CARGO { // ID character varying(36) NOT NULL, [Key] [Column("ID")] public string ID { get; set; } // CARGO_ID character varying(255) , [Column("CARGO_ID")] public string CARGO_ID { get; set; } // CARGO_NAME character varying(255) , [Column("CARGO_NAME")] [MaxLength(255)] public string CARGO_NAME { get; set; } }
-
-
定义EF的上下文,将表与数据库联系起来
-
public class KJZMMSContext : DbContext { public KJZMMSContext(DbContextOptions<KJZMMSContext> options) : base(options) { Console.WriteLine("执行了"); } public DbSet<T_CARGO> T_CARGOSet { get; set; } }
-
-
从控制台项目启动,创建数据库上下文
-
数据库连接字符串可从配置文件读取
-
你可能不是像网上的大部分博客那样,使用依赖注入的方式创建的,那正好,我这里就是手动创建的
-
DbContextOptionsBuilder<KJZMMSContext> builder = new DbContextOptionsBuilder<MMSContext>().UseOscar("Server=*.*.*.*;Port=2003;Database=OSRDB;Encoding=UTF-8;User Id=**;Password=**", action => { action.UseDefaultSchema("****"); action.UseCaseSensitive(); }); // 自行创建EF上下文 mmsContext = new MMSContext(builder.Options);
-
总结事项
- MaxLength这个特性,我刚开始是忽略的,所以插入数据时,总是报错,而且报错信息很不明朗,令人抓狂,错误信息如下
- 字符串溢出, value too long for type character varying(255)
- 我真的是吐了,这个报错害得我不断的去修改数据库字段长度,我以为插入的字符串长度太长了。
- 定义实体类和表的关系,俩种方式,一种是fluent api,另一种就是特性了,我还是不太习惯那种常常的api,除非是框架生成的,不然不想那样写。
- 控制台只是启动方式,创建EF上下文时,还是在工具类中使用静态代码块实现的
附录代码
- 用到的EFHelper类
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
namespace KZDBMS.EFCoreModule.DataHelper
{
public class EFHelper
{
public DbContext DatabaseContext { get; set; }
public EFHelper(DbContext dbContext)
{
this.DatabaseContext = dbContext;
}
//protected DbContext DatabaseContext
//{
// get
// { //为了保证线程唯一性,用线程槽存放
// // DbContext dbContext = CallContext.GetData("dbContext") as DbContext;
// if (dbContext == null)
// {
// //为空则创建新的上下文并放入线程槽
// //dbContext = new MPMS20190522Entities();
// dbContext = new AHDCEntities();
// CallContext.SetData("dbContext", dbContext);
// }
// return dbContext;
// }
//}
/// <summary>
/// 查询过滤
/// </summary>
/// <typeparam name="C"></typeparam>
/// <param name="whereLambda"></param>
/// <param name="orderBy"></param>
/// <returns></returns>
public IQueryable<T> GetAllEntities<T>(System.Linq.Expressions.Expression<Func<T, bool>> whereLambda) where T : class, new()
{
return DatabaseContext.Set<T>().Where(whereLambda);
}
/// <summary>
/// 分页查询
/// </summary>
/// <returns></returns>
public IQueryable<T> SelectByPage<T, C>(System.Linq.Expressions.Expression<Func<T, bool>> whereLambda, System.Linq.Expressions.Expression<Func<T, C>> orderBy, int pageIndex, int pageSize, bool isAsc, out int totalCount) where T : class, new()
{
var temp = DatabaseContext.Set<T>().Where<T>(whereLambda);
totalCount = temp.Count();
if (isAsc)
{
//升序取,取得时候跟了泛型
temp = temp.OrderBy<T, C>(orderBy).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
}
else
{
//降序取,取得时候没跟泛型
temp = temp.OrderByDescending<T, C>(orderBy).Skip((pageIndex - 1) * pageSize).Take(pageSize);
}
return temp;
}
/// <summary>
/// 增加数据
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public T Add<T>(T entity) where T : class, new()
{
//DbContext.Entry<T>(entity).State = EntityState.Added;
//return DbContext.SaveChanges() > 0;
DatabaseContext.Set<T>().Add(entity);
//DbContext.SaveChanges(); //注释掉此处保存操作,改为统一保存
return entity;
}
/// <summary>
/// 删除数据
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public bool Delete<T>(T entity) where T : class, new()
{
//DbContext.Entry<T>(entity).State = EntityState.Deleted;
DatabaseContext.Set<T>().Remove(entity);
//return DbContext.SaveChanges() > 0; //注释掉此处保存操作,改为统一保存
return true;
}
/// <summary>
/// 更新数据
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public bool Update<T>(T entity) where T : class, new()
{
DatabaseContext.Entry<T>(entity).State = EntityState.Modified;
//return DbContext.SaveChanges() > 0; //注释掉此处保存操作,改为统一保存
return true;
}
/// <summary>
/// 保存所作的更改
/// </summary>
/// <returns></returns>
public bool SaveChanges()
{
return DatabaseContext.SaveChanges() > 0;
}
}
}
-
一段反射去除字符串敏感词的代码
public static void ReplaceSensitiveKey(Object obj) { // TODO 脱敏操作 var properties = obj.GetType().GetProperties(); foreach (var property in properties) { if (property.PropertyType == typeof(string)) { // 只要是字符串类型的,都要进行脱敏操作 string propValue = (string) property.GetValue(obj); propValue = propValue == null ? null : propValue.Replace("敏感词", "和谐词").; property.SetValue(obj, propValue); } Console.WriteLine(property.Name); } }
参考文献
- ShenTong.EFCore: 神通数据库+Entity Framework Core+DotNet Core Web Api搭建的一个小示例! (gitee.com)
- .net core EF不用依赖注入的方式创建上下文对象 - it610.com