实体框架——在创建模型时不能使用上下文

本文关键字:不能 上下文 模型 框架 创建 实体 | 更新日期: 2023-09-27 18:02:05

我试图创建一个控制台应用程序,我试图使用实体框架来动态创建数据库和表来存储数据。然而,当我试图添加数据到我的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>

实体框架——在创建模型时不能使用上下文

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

如果在数据库尚未创建时出现此问题,则通常是连接字符串问题或数据库初始化器问题。您的连接字符串看起来没问题,因此它可以在实例构造函数中具有初始化项。尝试将初始化式移动到静态构造函数:

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; }
}

这对我来说很有效:创建上下文后初始化数据库

context.Database.Initialize(force: false);

对于我来说,问题是它是静态的或切碎的函数…

将其改为Public

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

在这里找到

我发现这个问题似乎发生了,因为控制器没有处理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()
    {
        //....
    }

但是你为什么要这样抓取数据呢?为什么要使用单独的类呢?这一切都应该发生在控制器中。你不想让它在所有东西上都是公共的和静态的——它是动态的,需要命名为&

我会这样做:

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();
    }
....
}