从 EF6 迁移到 EF Core 2.0

Posted

技术标签:

【中文标题】从 EF6 迁移到 EF Core 2.0【英文标题】:Moving from EF6 to EF Core 2.0 【发布时间】:2018-08-15 06:53:10 【问题描述】:

我刚开始将使用 EF6x 的 MVC5 项目迁移到 MVC Core 和 EF Core,但我的实体配置存在很大问题。如何将 EF6 Fluent 配置迁移到 EF 核心? 如果可能的话,我需要一个带样本的指南。

这是我的一个映射类和我的尝试

EntityMappingConfiguratuin

public interface IEntityMappingConfiguration

    void Map(ModelBuilder b);


public interface IEntityMappingConfiguration<T> : EntityMappingConfiguration where T : class

    void Map(EntityTypeBuilder<T> builder);


public abstract class EntityMappingConfiguration<T> : EntityMappingConfiguration<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<>));
        foreach (var config in mappingTypes.Select(Activator.CreateInstance).Cast<IEntityMappingConfiguration>())
        
            config.Map(modelBuilder);
        
    

DbContext

public class CommerceServiceDbContext : AbpDbContext
    
        public CommerceServiceDbContext(DbContextOptions<CommerceServiceDbContext> options) 
            : base(options)
        
        

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        
            modelBuilder.AddEntityConfigurationsFromAssembly(GetType().Assembly);
        
    

简单的旧配置

public partial class AffiliateMap : EntityMappingConfiguration<Affiliate>

    public override void Map(EntityTypeBuilder<Affiliate> b)
    
        b.ToTable("Affiliate");
        b.HasKey(a => a.Id);
        b.HasRequired(a => a.Address).WithMany().HasForeignKey(x => x.AddressId).WillCascadeOnDelete(false);
    

我的尝试

public partial class AffiliateMap : EntityMappingConfiguration<Affiliate>

    public override void Map(EntityTypeBuilder<Affiliate> b)
    
        b.ToTable("Affiliate");
        b.HasKey(a => a.Id);
        b.HasOne(a => a.Address)
            .WithMany().HasForeignKey(x => x.AddressId).IsRequired().OnDelete(DeleteBehavior.Restrict);
    


我使用 Google 搜索和 Microsoft 文档完成了这项工作。但我不确定我的工作。由于我有 +100 个配置课程,所以在继续之前我会问你。如果我的问题内容与网站的条款和条件不符,我深表歉意。

【问题讨论】:

我所知道的唯一转换工具是人类开发人员。 您的转换看起来没问题。关你什么事?您有具体问题吗? 对于测试运行,您只能配置部分实体,其余部分稍后配置。自己尝试是无可替代的。 感谢您花时间阅读我的帖子@IvanStoev 另外,请注意 EF 内核的映射选项与 EF6 不同。例如,不支持带有隐藏连接类的多对多,但添加了其他选项,例如更多方式来模拟一对一关联和使用备用键。这可能是从未实施自动转换的原因之一。 【参考方案1】:

我找到了一篇关于迁移到 EF 核心的好文章。我想分享这一点,并将这个问题留给像我这样的初学者。

代码更新 命名空间 System.Data.Entity 替换为 Microsoft.EntityFrameworkCoreHasDatabaseGeneratedOption(DatabaseGeneratedOption.None) 替换为 ValueGeneratedNever();DbContext 的基本构造函数没有用于连接字符串的单个字符串参数。我们现在必须注入 DbContextOptionsOnModelCreating(DbModelBuilder modelBuilder) 变为 OnModelCreating(ModelBuilder modelBuilder)。简单的更改,但更改都一样modelBuilder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly()); 不再可用,这意味着EntityTypeConfiguration 也不可用,所以我不得不将我的所有实体配置移动到OnModelCreating((IObjectContextAdapter)context).ObjectContext.ObjectMaterialized 不可用更长的可用时间。我用它来扩展 DbContext 以将所有日期转换为 Utc。我还没有找到替代品。ComplexType 不再可用。我不得不稍微更改模型结构以适应这一点。MigrateDatabaseToLatestVersion 不再可用,因此我不得不将以下内容添加到我的 startup.cs

using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())

    serviceScope.ServiceProvider.GetService<SbDbContext>().Database.Migrate();

WillCascadeOnDelete(false) 变为 OnDelete(DeleteBehavior.Restrict)HasOptional 根据帖子不再相关IDbSet 变为 DbSetDbSet&lt;T&gt;.Add() 不再返回 TEntityEntry&lt;T&gt;

var entry = context.LearningAreaCategories.Add(new LearningAreaCategory());
//that's if you need to use the entity afterwards
var entity = entry.Entity;

IQueryable&lt;T&gt;.Include(Func&lt;&gt;) 现在返回IIncludableQueryable&lt;T,Y&gt; 而不是IQueryable&lt;T&gt;,同样适用于OrderBy。我所做的就是将所有的 include 和 orderby 移到最后。

来源:Moving from EF6 to EF Core

【讨论】:

以上是关于从 EF6 迁移到 EF Core 2.0的主要内容,如果未能解决你的问题,请参考以下文章

将现有 Microsoft.AspNet.Identity DB (EF 6) 迁移到 Microsoft.AspNetCore.Identity (EF Core)

执行迁移 EF core 2.0 时出错,将身份 ID 从字符串更改为 int

EF5+SQLserver2012迁移到EF6+mysql5.5.47

EF5+SQLserver2012迁移到EF6+mysql5.5.47

EF6 学习笔记:数据库迁移及部署

EF6 Codefirst+MySql 数据库迁移