EF Core手动创建实体类操作数据库

业务场景

  • 俩个数据库之间的数据需要迁移,然后表的结构不同,且迁移过程中还涉及到一丢丢数据的加工处理,因此不能简单的使用导入导入,然后列映射的功能完成任务了
  • .net core的nuget包,刚好有对应数据库的驱动,另外刚开始,是不想写实体类的,指望着使用DBFirst模式生成代码(EF Core里面,好像已经不叫DB First了)
  • 后来,从数据库表生成代码失败了。。。所以选择手写实体类来映射数据库表

技术实现

虚空代码

  • 引入需要的nuget包
  • 创建实体类
  • 创建EF的上下文,并且把实体类对应的数据集属性DBSet手动填上
  • 控制台项目启动,创建不同的数据库上下文,开始处理数据

实际开发

  • 需要引入的包,不仅EF Core所在的项目需要,解决方案的启动项目也需要

    • 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; }
           }
      
  • 从控制台项目启动,创建数据库上下文

    1. 数据库连接字符串可从配置文件读取

    2. 你可能不是像网上的大部分博客那样,使用依赖注入的方式创建的,那正好,我这里就是手动创建的

    3.          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);
                }
    
            }
    

参考文献

上一篇:FireDAC分页查询


下一篇:Android Architecture Components 之 Room 篇,flutter消息推送收费