繁体   English   中英

实体框架 - 创建模型时无法使用上下文

[英]Entity Framework - The context cannot be used while the model is being created

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

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

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

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

错误发生在行

this.context.Environments.Add(entity)

数据源文件

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

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

这里找到

我发现这个问题似乎是因为 Controller 不负责处理 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();
    }
....
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM