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

时间:2016-08-11 16:05:01

标签: c# entity-framework

我正在尝试创建一个控制台应用程序,我试图使用Entity Framework动态创建数据库和表来存储数据。但是,当我尝试将数据添加到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>

5 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:3)

如果尚未创建数据库,则通常是连接字符串问题或数据库初始化程序问题。您的连接字符串看起来没问题,因此它可能在实例构造函数中具有初始化程序。尝试将初始值设定项移至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; }
}

答案 2 :(得分:0)

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

context.Database.Initialize(force: false);

答案 3 :(得分:0)

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

将其更改为公开

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

找到了here

答案 4 :(得分:0)

我发现出现此问题的原因是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()
    {
        //....
    }

但是为什么要像这样抓取数据?为什么要使用单独的类?这都应该在控制器中发生。而且您不想尝试使其在所有事物上都是公共的和静态的-它是动态的,需要按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();
    }
....
}