【问题标题】:The context cannot be used while the model is being created exception [closed]创建模型时无法使用上下文异常[关闭]
【发布时间】:2021-07-11 16:05:55
【问题描述】:

使用Entity Framework 6.0.0.0 时出现以下错误。

在创建模型时不能使用上下文。 如果在
内部使用上下文,则可能会引发此异常 OnModelCreating 方法或 如果相同的上下文实例 由多个线程同时访问。 请注意,DbContext 的实例成员和 不保证相关类是线程安全的。 它在 async 方法内触发 ,更新

   public async Task<IList<Model>> GetEntities(filter f)
   {
        using (var db = new MyDbContext())
        { 
           var query = db.MyDbSet.AsQueryable();

            if (f != null && f.field.Any())
               //Exception throwed here
                query = query.Where(a => f.field.Contains(a.field));

        return await query.ToListAsync();
       }
 }

但是当我尝试通过Where 子句查找我的实体时,不会执行任何await 调用或其他多线程操作。

是否有与该问题相关的建议?我找到了很多答案,但没有发现它们对我有帮助。

【问题讨论】:

  • 贴出更完整的代码。正如您可能想象的那样,这段代码看起来完全是无辜的,无法从中诊断出来。
  • @usr 我添加了代码
  • 好的。现在请完整的异常 ToString 因为代码对我来说很好。
  • 看来原因是下面的错误Additional information: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) 但是Management studio已经连接没有问题。以下连接字符串对于 win auth Data Source=host;Initial Catalog=database;Integrated Security=True; 是否正确?
  • 听起来这两个错误不相关。再次,发布完整的 ToString 输出。里面有很多信息。

标签: c# entity-framework async-await


【解决方案1】:

如果您的管理工作室已经能够成功连接到数据库 然后这样做。在连接到数据库之前运行您的管理工作室 复制完整的“服务器名称”并使用它来替换您的“主机”并确认您尝试连接到的特定数据库的实际名称称为“数据库”,如果没有用该名称替换“数据库”。最后,如果您的管理工作室需要用户名和密码才能连接到数据库,那么您也必须包括这些。从错误中您得到的问题是连接到您的数据库。让我知道事情的后续。

【讨论】:

    【解决方案2】:

    您想要实现一个适当的方法来连接到您的数据库以处理连接,或者使用称为“依赖注入”的术语 - 创建一个接口和 DataContext 的实例,该接口和实例可以随时被任何函数访问在控制器中。以下是这 2 种方法的示例:

    处置架构

    此架构要求您在任何其他函数之前声明您的 DataContext,并在最后在 Controller 中添加一个 Dispose 函数。

    我在代码中发现并修复了一些特定的奇怪之处:

    • 您应该返回一个 ViewModel 或一个代表您正在查询的数据库表或视图的数据模型,在本例中为 MyDbSet,而不是 Model
    • 您应该使用为该类通用声明的db 实例。
    • 您应该定义filter 是什么。数组?一个模型?一个字符串?我将假设它是这样的字符串列表:string[] filter = { "Fruits", "Meats", "Dairy" };
    • Where 子句在您的查询中可能不正确,但同样,我不知道您的 filter 是什么样的。这里还有其他例子:https://docs.microsoft.com/en-us/dotnet/api/system.linq.queryable.where?view=netframework-4.8

      MyDbContext db = new MyDbContext();
      
      public async Task<IList<MyDbSet>> GetEntities(filter f)
      {
          using (db)
          { 
              var query = null;
              if (f != null && f.field.Any())
              {
                  query = db.MyDbSet.AsQueryable().Where((a, index) => a == f);
              }
              return await query.ToListAsync();
          }
      }
      
      protected override void Dispose(bool disposing)
      {
          if (disposing)
          {
              db.Dispose();
          }
          base.Dispose(disposing);
      }
      

    依赖注入

    我在另一篇 SO 帖子中详细描述了这个过程,这里:

    How to inject my dbContext with Unity

    主要区别在于您可以在控制器的 GetEntities 函数中执行类似的操作来获取数据:

    query = repository.GetMyDbSet.Where((a, index) => a == f);
    

    与上述基本相同,但您不再需要 using(db) { ... } 语句。

    你会有一个界面:

    public interface IDataRepository
    {
        void SaveChanges();
        IEnumerable<MyDbSet> GetMyDbSet();
    }
    

    以及将数据返回给您的存储库类函数:

    public IEnumerable<MyDbSet> GetMyDbSet()
    {
        return context.MyDbSet;
    }
    

    context 是在一个Repository 类中定义的:

    public class DataRepository : IDataRepository
    {
        private bool disposing;
        private readonly MyDbContext context;
    
        public virtual void Dispose()
        {
            if (disposing)
            {
                return;
            }
    
            disposing = true;
    
            if (context != null)
            {
                context.Dispose();
            }
        }
    
        public void SaveChanges()
        {
            context.SaveChanges();
        }
    
        public DataRepository()
        {
            context = new MyDbContext();
            context.Configuration.ProxyCreationEnabled = false;
        }
    
        public IEnumerable<MyDbSet> GetMyDbSet()
        {
            return context.MyDbSet;
        }
    }
    

    希望这对您或某人有所帮助。

    【讨论】:

      猜你喜欢
      • 2014-02-16
      • 2015-11-14
      • 1970-01-01
      • 2014-06-11
      • 1970-01-01
      • 1970-01-01
      • 2016-01-13
      相关资源
      最近更新 更多