You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VS2022迁移后EF 6.4.4出现ConceptualModels标签不匹配问题求助

问题描述

从Visual Studio 2017迁移到Visual Studio 2022时,先遇到Entity Framework错误“Value cannot be null. Parameter name: type”,于是将Entity Framework 6.2.0升级至6.4.4。执行数据库更新操作时,出现XML标签不匹配错误:第4行第6位的ConceptualModels起始标签与第1747行第7位的ConceptualModessociationSet结束标签不匹配。项目采用CodeFirst模式。

错误堆栈信息:

at System.Xml.XmlTextReaderImpl.ParseElementContent()
   at System.Xml.Linq.XContainer.ReadContentFrom(XmlReader r)
   at System.Xml.Linq.XContainer.ReadContentFrom(XmlReader r, LoadOptions o)
   at System.Xml.Linq.XDocument.Load(XmlReader reader, LoadOptions options)
   at System.Xml.Linq.XDocument.Load(Stream stream, LoadOptions options)
   at System.Data.Entity.Migrations.Edm.ModelCompressor.Decompress(Byte[] bytes)
   at System.Data.Entity.Migrations.DbMigration.GetModel(Func`2 modelAccessor)
   at System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ApplyMigration(DbMigration migration, DbMigration lastMigration)
   at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)
   at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
   at System.Data.Entity.Infrastructure.Design.Executor.Update.<>c__DisplayClass0_0.<.ctor>b__0()
   at System.Data.Entity.Infrastructure.Design.Executor.OperationBase.Execute(Action action)
The 'ConceptualModels' start tag on line 4 position 6 does not match the end tag of 'ConceptualModessociationSet'. Line 1747, position 7.

DBContext代码:

namespace GMM.Repository.Context
{
    public class GMMDbContext : IdentityDbContext<ApplicationUser, AppRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
    {
        public static string ConnectionString { get; set; }
        static GMMDbContext()
        {
#if DEBUG
            ConnectionString = "GMMConnection";
#endif
        }
        public static GMMDbContext Create()
        {
            return new GMMDbContext();
        }

        public GMMDbContext()
            : base(ConnectionString)             
        {
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<GMMDbContext, GMM.Repository.Migrations.Configuration>());
            DbInterception.Add(new FtsInterceptor());
        }

        #region AccessControl
        public IDbSet<GroupRole> GroupRoles { get; set; }
        public IDbSet<RoleGroup> RoleGroups { get; set; }
        public IDbSet<UserRoleGroup> UserRoleGroups { get; set; }
        #endregion

        #region BaseInformation
        public IDbSet<Department> Departments { get; set; }
        #endregion

 

        #region General
        public IDbSet<Location> Locations { get; set; }

        public IDbSet<Setting> Settings { get; set; }
  
        #endregion

     


        public int SaveChanges(string currentUserIp)
        {
            AddTimestamps(currentUserIp);
            return base.SaveChanges();
        }

        public Task<int> SaveChangesAsync(string userIp)
        {
            AddTimestamps(userIp);
            return base.SaveChangesAsync();
        }

        public override int SaveChanges()
        {
            AddTimestamps();
            return base.SaveChanges();
        }

        private void AddTimestamps(string currentUserId, string currentUserIp)
        {
            if (currentUserId == null)
            {
                throw new NullReferenceException("CurrentUserId");
            }

            var entities = ChangeTracker.Entries().Where(x => x.Entity is IBaseEntity && (x.State == EntityState.Added || x.State == EntityState.Modified));
            foreach (var entity in entities)
            {
                if (entity.State == EntityState.Added)
                {
                    ((BaseGuidEntity)entity.Entity).DateCreated = DateTime.Now;
                    ((BaseGuidEntity)entity.Entity).CreatedBy_Id = currentUserId;
                    ((BaseGuidEntity)entity.Entity).CreatedByIp = currentUserIp;
                }

                ((BaseGuidEntity)entity.Entity).DateModified = DateTime.Now;
                ((BaseGuidEntity)entity.Entity).ModifiedBy_Id = currentUserId;
                ((BaseGuidEntity)entity.Entity).ModifiedByIp = currentUserIp;
            }
        }

        private void AddTimestamps()
        {
            var entities = ChangeTracker.Entries().Where(x => x.Entity is IBaseEntity && (x.State == EntityState.Added || x.State == EntityState.Modified));
            foreach (var entity in entities)
            {
                if (entity.State == EntityState.Added)
                {
                    ((BaseGuidEntity)entity.Entity).DateCreated = DateTime.UtcNow;

                }
                ((BaseGuidEntity)entity.Entity).DateModified = DateTime.UtcNow;
            }
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            #region Message
            modelBuilder.Configurations.Add(new PrivacyConfig());
            modelBuilder.Configurations.Add(new ResultConfig());
            modelBuilder.Configurations.Add(new SubjectConfig());
            modelBuilder.Configurations.Add(new PriorityConfig());
            modelBuilder.Configurations.Add(new CategoryConfig());
            modelBuilder.Configurations.Add(new MessageConfig());
            modelBuilder.Configurations.Add(new MessageFeedbackConfig());
            modelBuilder.Configurations.Add(new ReferConfig());
            #endregion

            base.OnModelCreating(modelBuilder);
        }
    }
}

模型图:
我的模型图

解决方案
  • 修复迁移历史表中的损坏XML

    1. 连接目标数据库,找到__MigrationHistory表,定位对应迁移记录的Model字段(该字段为二进制存储的压缩XML)。
    2. 编写工具代码解压二进制数据:
      using System.Data.Entity.Migrations.Edm;
      using System.IO;
      using System.Xml.Linq;
      
      // 从数据库读取到的Model字段字节数组
      byte[] modelBytes = /* 读取数据库中的二进制数据 */;
      var decompressedData = ModelCompressor.Decompress(modelBytes);
      using (var ms = new MemoryStream(decompressedData))
      {
          var modelXml = XDocument.Load(ms);
          modelXml.Save("model.xml"); // 保存到本地文件查看
      }
      
    3. 打开model.xml文件,定位到第1747行,将错误的结束标签</ConceptualModessociationSet>修正为</ConceptualModels>(该错误是标签拼接失误,将ConceptualModels与AssociationSet错误合并)。
    4. 将修正后的XML重新压缩,更新回__MigrationHistory表的对应记录:
      var correctedXml = XDocument.Load("corrected_model.xml");
      using (var ms = new MemoryStream())
      {
          correctedXml.Save(ms);
          ms.Position = 0;
          byte[] compressedBytes = ModelCompressor.Compress(ms.ToArray());
          // 将compressedBytes更新到数据库的Model字段
      }
      
  • 检查模型配置是否存在错误

    1. 查看OnModelCreating方法中添加的各类实体配置类(如PrivacyConfig、MessageConfig等),排查以下问题:
      • 重复定义的导航属性
      • 错误的外键关联设置
      • 多对多关系配置失误
    2. 对照模型图,确认所有实体间的关联关系是否正确,避免因模型结构问题导致生成的ConceptualModels XML异常。
  • 重置迁移(备选方案,需谨慎操作)
    若迁移历史损坏严重无法单独修复,可尝试重置迁移流程:

    1. 备份当前数据库,避免数据丢失。
    2. 删除项目中Migrations文件夹下的所有迁移文件。
    3. 删除数据库中的__MigrationHistory表。
    4. 在Package Manager Console中执行以下命令:
      Enable-Migrations -Force
      Add-Migration Initial
      Update-Database -Script
      
    5. 对比生成的SQL脚本与现有数据库结构,调整后再执行脚本,确保数据不会被覆盖。

内容的提问来源于stack exchange,提问作者MR Alam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 16:25:27