zoukankan      html  css  js  c++  java
  • .NET Core、EF、Dapper、MySQL 多种方式实现数据库操作(动态注册实体类)

    目录

    前言

    最近在学习、研究 .NET Core 方面的知识,动手搭建了一些小的 Demo,对 .NET Core 有了初步的认识了解。

    恰逢公司的项目需要,有一个需求,不大不小可以作为转 .NET Core 的示例项目来做。

    这个项目的搭建工作由我来做,我这边做了一些技术预研,对呀用到的技术进行预研,其中包括:Kafka、SignalR、Topshelf。

    但是在做单数据库的时候出现了一些问题。

    一、技术选型

    这里说的技术选型是数据操作这一块的。

    我们之所以选择了 EF、Dapper 结合,是有原因的。以前是直接用的 EF DBFirst 直接拖库过来,用 Linq 语句查询,但是这样对于多张表的连表查询存在很大的隐患,因为这样生成的 SQL 语句不可靠,有时候生成的太复杂,效率太低,所以最终选择了 EF 和 Dapper 结合。对于简单的查询直接用 EF 操作,对于复杂一些的查询写 SQL 语句用 Dapper 查询。

    这个选型是原先 .NET 下的,这次转的话,也按照这个来。

    二、遇到的坑

    在具体的实施中遇到了几个坑,下面就展开说说。

    2.1、.NET Core 下 EF 的问题

    .NET  Core 下的 EF 和原先平台的有挺大的差别,首先构造函数的差别:

    .NET  下的

    public DbContext(string nameOrConnectionString);
    
    public DbContext(string nameOrConnectionString, DbCompiledModel model);
    
    public DbContext(DbConnection existingConnection, bool contextOwnsConnection);
    
    public DbContext(ObjectContext objectContext, bool dbContextOwnsObjectContext);
    
    public DbContext(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection);
    
    protected DbContext();
    
    protected DbContext(DbCompiledModel model);

    .NET Core 下的

    public DbContext([NotNullAttribute] DbContextOptions options);
    
    protected DbContext();

    主要是因为 .NET Core 下功能模块的注册使用的新的方式。

    那么在.NET Core 下继承 DbContext 并对其扩展如下:

    public class DbContextTest : DbContext
        {
            public DbContextTest(DbContextOptions<DbContextTest> options)
                : base(options)
            {
            }
        }
    public class MySQLDatabase
        {
            #region 构造函数
            /// <summary>
            /// 构造方法
            /// </summary>
            /// <param name="connString">连接串</param>
            public MySQlDatabase(string connString)
            {
                var optionBuilder = new DbContextOptionsBuilder<DatabaseContext>();

            optionBuilder.UseMySql(connString, mysqlOptions =>
            {
              mysqlOptions.ServerVersion(new Version(5, 7, 22), Pomelo.EntityFrameworkCore.MySql.Infrastructure.ServerType.MySql);
            });

                dbcontext = new DatabaseContext(optionBuilder.Options);
                Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
            }

         // 这里是扩展的一些方法 }

    2.2、数据库实体类的注册

    因为选择了 EF 和 Dapper 那么需要自己动态建实体类并注册。

    原先写了一个实体类生成的工具,这里拿来直接用了,在注册的时候 EF 和以前的注册方式有了改变,这里有对其扩展的代码:

    namespace DataBase.Mapping
    {
        public interface IEntityMappingConfiguration
        {
            void Map(ModelBuilder b);
        }
    
        public interface IEntityMappingConfiguration<T> : IEntityMappingConfiguration where T : class
        {
            void Map(EntityTypeBuilder<T> builder);
        }
    
        public abstract class EntityMappingConfiguration<T> : IEntityMappingConfiguration<T> where T : class
        {
            public abstract void Map(EntityTypeBuilder<T> b);
    
            public void Map(ModelBuilder b)
            {
                Map(b.Entity<T>());
            }
        }
    
        public static class ModelBuilderExtenions
        {
            private static IEnumerable<Type> GetMappingTypes(this Assembly assembly, Type mappingInterface)
            {
                return assembly.GetTypes().Where(x => !x.IsAbstract && x.GetInterfaces().Any(y => y.GetTypeInfo().IsGenericType && y.GetGenericTypeDefinition() == mappingInterface));
            }
    
            public static void AddEntityConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
            {
                var mappingTypes = assembly.GetMappingTypes(typeof(IEntityMappingConfiguration<>));
                IEnumerable<IEntityMappingConfiguration> configs = mappingTypes.Select(Activator.CreateInstance).Cast<IEntityMappingConfiguration>();
                foreach (var config in configs)
                {
                    config.Map(modelBuilder);
                }
            }
        }
    }

    实体类的 Mapping,这个是继承了上面的接口 :

        public class ApplicationMap : EntityMappingConfiguration<ApplicationEntity>
        {
            public override void Map(EntityTypeBuilder<ApplicationEntity> b)
            {
                b.ToTable("application")
                    .HasKey(p => p.Id);
            }
        }

    那么在 DbContextTest 里面重写 OnModelCreating 方法:

            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
    
                string assembleFileName = Assembly.GetExecutingAssembly().CodeBase.Replace("DataBase.dll", "Mapping.dll").Replace("file:///", "");
                Assembly asm = Assembly.LoadFile(assembleFileName);
                modelBuilder.AddEntityConfigurationsFromAssembly(asm);
            }

    这样代码工作基本完成了。

    切记坑:

    开始用的是 MySQL 官方的驱动:MySql.Data.EntityFrameworkCore ,但是一直报错:" The 'MySQLNumberTypeMapping' does not support value conversions. "

    后来改用 Pomelo.EntityFrameworkCore.MySql 就可以了。

    这个坑困扰了几天,真是憔悴了些。

  • 相关阅读:
    Node Sass version 5.0.0 is incompatible with^4.0.0
    解决vue-cli引入sass,报错:this.getResolve is not a function问题
    解决nuxt官方脚手架的一些坑:1、支持es6+语法 2、样式支持sass
    针对【create-nuxt-app新版本v3.2.0】构建项目时没有server配置以及运行后弹出收集匿名数据选项等问题的解决方法
    create-nuxt-app创建出来的目录没有server文件夹
    Redis安装(Windows环境下Redis安装)
    koa2中间件,路由,cookies
    用同步的写法来执行异步操作, async, awiat
    koa2 安装与启动
    练习:自己写一个容器ArrayList集合 一一数组综合练习
  • 原文地址:https://www.cnblogs.com/zhurong/p/9804790.html
Copyright © 2011-2022 走看看