【问题标题】:Entity Framework - The context cannot be used while the model is being created实体框架 - 创建模型时不能使用上下文
【发布时间】:2016-12-18 11:34:35
【问题描述】:

我正在尝试创建一个控制台应用程序,我正在尝试使用实体框架来动态创建数据库和表来存储数据。但是,当我尝试将数据添加到我的 DbSet 时。我收到以下错误。

“System.InvalidOperationException”类型的未处理异常 发生在EntityFramework.dll中

附加信息:模型在运行时不能使用上下文 正在创建。如果使用上下文,可能会抛出此异常 在 OnModelCreating 方法内,或者如果相同的上下文实例是 由多个线程同时访问。请注意,实例成员 不保证 DbContext 和相关类是线程安全的。

我参考了其他有类似错误的帖子,但没有一个解决方案有效。这是一个单线程应用程序。

错误发生在行

this.context.Environments.Add(entity)

DataSource.cs

public class DataSource
{
        private static DataSource instance;

        public DataSource()
        {
            this.context = new CounterContext();
        }

        public static DataSource Instance
        {
            get
            {
                return instance ?? (instance = new DataSource());
            }
        }

        private CounterContext context;

        public void AddCockpitEnvironmentDetails(IList<Environment> environmentList)
        {
            foreach (var entity in environmentList)
            {
                this.context.Environments.Add(entity);
            }

            this.context.SaveChanges();
        }
...
}

我的背景:

public class CounterContext : DbContext
{
        public CounterContext()
            : base("name=CounterDbString")
        {
            Database.SetInitializer<CounterContext>(new CreateDatabaseIfNotExists<CounterContext>());
        }
        public DbSet<CounterData> CounterDetails { get; set; }

        public DbSet<Environment> Environments { get; set; }
    }

型号

public class Environment
{
    [Key]
    public Guid Id { get; set; }
    public string EnvironmentName { get; set; }
    public string EnvironmentNotes { get; set; }

    public virtual ICollection<CounterDetail> CounterDetails { get; set; }
};

public class CounterData 
{
    [Key]
    [Column(Order = 1)]
    public DateTime counterTime { get; set; }
    [Key]
    [Column(Order = 2)]
    public int counterName { get; set; }
    [Key]
    [Column(Order = 3)]
    public Guid EnvId {get; set;}
    public int count { get; set; }

    [ForeignKey("EnvId")]
    public virtual CockpitEnvironment Machine { get; set; }
}

App.config:

<connectionStrings>
    <add name="CounterDbString" 
         connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=Counters_Test;Integrated Security=True;Connect Timeout=30"
         providerName="System.Data.SqlClient"/>
</connectionStrings>

【问题讨论】:

  • 从你的构造函数中移除 this.context 并将其添加到方法 AddCockpitEnvironmentDetails 中并查看
  • 不工作。但是我做了一个实验,首先在 SQL Server 中添加 mdf 文件,然后运行代码。有效。所以问题是它无法创建表。但不确定如何解决此问题。

标签: c# entity-framework


【解决方案1】:

使用 VS2015,在调试 (F5) 时出现此错误。简单地停止调试器并重新启动后,问题就消失了。

【讨论】:

  • VS2013 出现同样的问题
【解决方案2】:

如果在您的数据库尚未创建时出现此问题,通常是连接字符串问题或数据库初始化程序问题。您的连接字符串看起来不错,因此它可能在实例构造函数中包含初始化程序。尝试将初始化程序移动到 static constructor:

public class CounterContext : DbContext
{
    static CounterContext  // runs once
    {
        Database.SetInitializer<CounterContext>(new CreateDatabaseIfNotExists<CounterContext>());
    }

    public CounterContext()
        : base("name=CounterDbString") { }

    public DbSet<CounterData> CounterDetails { get; set; }

    public DbSet<Environment> Environments { get; set; }
}

【讨论】:

  • 解决了这个问题。请看上面的评论。试图找出解决方案。我很确定我在这里遗漏了一些微不足道的东西。有什么想法吗?
  • 通过手动创建数据库,您的初始化程序不会运行 (CreateDatabaseIfNotExists)。你把这个问题推到了地毯下,但它可能会在稍后出现。
  • 添加静态构造函数会出现错误:The name 'Database.SetInitializer&lt;CounterContext&gt;' does not exist in the current context. 和括号(即使我匹配它们),Invalid token '{' in class, struct, or interface member declaration。 @SteveGreene:不一定。如果它起作用了,那一行意味着它会在需要时创建实例——如果没有,它就不会。如果没有,则意味着它有它需要的东西,所以它永远不会失败(至少在理论上)。
  • @vapcguy 您是在询问错误还是提供更正?
  • @SteveGreene Ah-没有意识到你既是问题的回答者又是评论者(哦!)。我试图在 1 篇文章中解决这两个问题,并认为你说它是在说它扫清了“地毯下的问题”,从而反对你自己的答案。我试图纠正这一点——使用CreateDatabaseIfExists 不应该那样做。但我发现在您的原始答案中建议将Database.SetInitializer&lt;CounterContext&gt;(new CreateDatabaseIfNotExists&lt;CounterContext&gt;()); 添加到我的项目时出现错误。如果您有任何其他信息说明您必须采取哪些措施来避免我收到的错误,我们将不胜感激。
【解决方案3】:

这对我有用: 创建上下文后初始化数据库

context.Database.Initialize(force: false);

【讨论】:

    【解决方案4】:

    对我来说,问题在于它是静态或切碎功能......

    将其更改为公开

    线程安全:这种类型的任何公共静态(在 Visual Basic 中为共享)成员都是线程安全的。不保证任何实例成员都是线程安全的。

    找到here

    【讨论】:

      【解决方案5】:

      我发现这个问题似乎是因为控制器不负责处理 DataContext 并且它保持打开状态。您可以在 DataContext 端或控制器端处理此问题,或两者兼而有之。

      我在我的 DataContext 中这样做:

      public partial class Model1 : DbContext
      {
          public Model1()
              : this(true)
          { }
      
          public Model1(bool enableLazyLoading = true)
              : base("name=Model1")
          {
              // You can also do this instead of the other lines
              //Database.SetInitializer<Model1>(new CreateDatabaseIfNotExists<Model1>());            
              //this.Configuration.LazyLoadingEnabled = false;
      
              Database.SetInitializer<Model1>(null);
              this.Configuration.ProxyCreationEnabled = false;
      
              ((IObjectContextAdapter)this).ObjectContext.ContextOptions.ProxyCreationEnabled = enableLazyLoading;
              ((IObjectContextAdapter)this).ObjectContext.ContextOptions.LazyLoadingEnabled = enableLazyLoading;
          }
      

      这在控制器中:

      public class ReportController : Controller
      {
          protected override void Dispose(bool disposing)
          {
              if (disposing)
              {
                  db.Dispose();
              }
              base.Dispose(disposing);
          }
      

      然后你就有了正常的东西......

          public ActionResult Index()
          {
              //....
          }
      

      但是你为什么要这样抓取数据?为什么要使用单独的课程?这一切都应该发生在 Controller 中。而且您不想尝试在所有内容中使其公开和静态 - 它是动态的,需要每个控制器调用和处置,而不是保持打开状态。

      我会这样做:

      public class ReportController : Controller
      {
          CounterContext db = new CounterContext();
      
          protected override void Dispose(bool disposing)
          {
              if (disposing)
              {
                 db.Dispose();
              }
              base.Dispose(disposing);
          }
      
          public void AddCockpitEnvironmentDetails(IList<Environment> environmentList)
          {
              // You could've gotten it like this instead of passing it in...
              // IEnumerable<Environments> environmentList = db.Environments;
      
              foreach (Environment entity in environmentList)
              {
                  db.Environments.Add(entity);
              }
      
              db.SaveChanges();
          }
      ....
      }
      

      【讨论】:

        猜你喜欢
        • 2016-01-13
        • 2015-11-14
        • 1970-01-01
        • 2017-08-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多