.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 就可以了。

這個坑困擾了幾天,真是憔悴了些。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM