【问题标题】:Entity Framework 6 exception: "The context cannot be used while the model is being created"实体框架 6 异常:“创建模型时无法使用上下文”
【发布时间】:2015-11-14 17:41:14
【问题描述】:

当我从旧式 ADO.NET 转向 Entity Framework 6 时,我有点陌生,所以请耐心等待。

我正在尝试创建一个新的 WPF MVVM 项目以及一些 WinForms,它们将直接使用 DBContext 而无需与 EF 6 进行数据绑定。

使用 Visual Studio 2013 实体框架向导,我通过逆向工程在我们的业务服务器上创建了一个代码优先的当前数据库。然后我将数据模型类与上下文分开

这是DbContext 代码:

namespace EFModels
{
    public partial class MyDataContext : DbContext
    {
        public MyDataContext () : base("name=MyDataContext")
        {
        }

        public virtual DbSet<Calibration> Calibrations { get; set; }
        public virtual DbSet<OrderDetail> OrderDetails { get; set; }
        public virtual DbSet<OrderHistory> OrderHistories { get; set; } 
        public virtual DbSet<WorkDetail> WorkDetails { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {   
            modelBuilder.Entity<WorkDetail>()
                    .HasMany(e => e.Calibrations)
                    .WithOptional(e => e.WorkDetail)
                    .HasForeignKey(e => e.WorkID);  
        }
    }
}

我已将数据类分隔在单独的命名空间中,例如:

namespace MyDataDomain
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;

    public partial class OrderDetail
    {
        public OrderDetail()
        {
            Calibrations = new HashSet<Calibration>();
            JournalEntryDatas = new HashSet<JournalEntryData>();
            OrderHistories = new HashSet<OrderHistory>();
            WorkDetails = new HashSet<WorkDetail>();
        }

        [Key]
        public long OrderID { get; set; }

        [StringLength(50)]  
        public string PONumber { get; set; }

        [Column(TypeName = "date")]
        public DateTime? Due { get; set; }

        [Column(TypeName = "date")]
        public DateTime? OrderDate { get; set; }

        [Column(TypeName = "date")]
        public DateTime? ShipDate { get; set; }

        [Column(TypeName = "text")]
        public string Comment { get; set; }

        public int? EnterByID { get; set; }

        public virtual ICollection<Calibration> Calibrations { get; set; }

        public virtual ICollection<JournalEntryData> JournalEntryDatas { get; set; }
        public virtual ICollection<OrderHistory> OrderHistories { get; set; }
        public virtual ICollection<WorkDetail> WorkDetails { get; set;      }
    }
}

其余类的风格类似,但是当使用外键约束时,它有这样的东西:

public virtual OrderDetail OrderDetail { get; set; }

因为在我们的小世界里,它会围绕着骑士团。

还有 app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0,         Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
  </startup>
  <connectionStrings>
    <add name="MyDataContext" connectionString="data source=BIZSERVER\SQL2008R2DB;initial catalog=Company;persist security info=True;user id=DaBossMan;password=none_of_your_damn_business;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="mssqllocaldb" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>

所以当我这样做时:

var context = New MyDataContext();
var list1 = context.JournalEntryDatas.ToList();
var list2 = context.OrderHistories.ToList();

抛出异常:

在创建模型时不能使用上下文。这 如果在内部使用上下文可能会引发异常 OnModelCreating 方法或者如果相同的上下文实例被访问 多个线程同时进行。注意DbContext 的实例成员 和相关的类不保证是线程安全的。

我在这里发疯了,试图弄清楚我能做什么,我一直在读到,也许做一个任务工厂可能会有所帮助,那么我该如何使用它从每个表中获取数据,这样我就可以填充列表?

或者我可以使用其他替代方法或解决方法吗?

编辑:这是(由 Andez 提出)要求的完整堆栈跟踪:

System.InvalidOperationException was caught
HResult=-2146233079
Message=The context cannot be used while the model is being created. This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.
Source=EntityFramework
StackTrace:
   at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
   at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
   at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
   at System.Data.Entity.Internal.Linq.InternalSet`1.GetEnumerator()
   at System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.Generic.IEnumerable<TResult>.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at MichellControls.JournalDataListView.JournalDataListView_Load(Object sender, EventArgs e) in c:\Users\Steve\Projects\Visual Studio 2013\Projects\MyControls\WinFormControls\JournalDataListView.cs:line 35
InnerException: 
    // (there wasn't any InnerException)

【问题讨论】:

  • 理想情况下,您需要将上下文包装在 using 语句中: using (var context = new MyDataContext() { var list1 = context.JournalEntryDatas.ToList(); var list2 = context.OrderHistories.ToList( ); } 但我看不出这是原因。
  • 我假设模型都是有效的,包括模型构建器中定义的关系?您是否尝试过从更少的模型类(比如两个)开始并从那里解决?还有 - 你有异常的调用堆栈吗?还要检查你的代码中没有发生任何可能从你的帖子中省略的异步调用。
  • 这通常发生在多线程代码和访问上下文时,它第一次被实例化并且已经从另一个线程构建模型。你只运行了那三行?
  • 抱歉,Andez,我只是将整个堆栈跟踪放入问题中,因为我无法将它放在 cmets 中。我希望这可以帮助你帮助我解决这个问题
  • @kmcc049:我也在想同样的事情,但我只是运行了一个 UserControl,因为我需要对其进行测试。它确实提出了如何封装 DbContext 以使其成为线程安全的问题。因此,为什么我要询问 TPL 或任务工厂。我看到其他使用 WebAPI 的人遇到与我相同的问题,但我在 WinForm 和 WPF 中使用它。我只是不知道如何使用其中任何一种方法......但是! :-)

标签: c# .net entity-framework-6


【解决方案1】:

你说你(是)实体框架的新手,所以也许值得指出DbContexts 不应该被共享和重用。通常,您需要在单个工作单元中创建、使用和处置 DbContext

换句话说,你不应该“共享”DbContext(例如,在启动时只创建一个并在多个地方使用它等等。你提到尝试创建一个“线程安全包装器”——你绝对不应该尝试从多个线程访问它(每个操作都有自己的 DbContext)

【讨论】:

    【解决方案2】:

    我认为这可能与 onModelCreating 中的外键创建有关。根据documentation,onMethodCreating 方法“在派生上下文的模型已初始化时调用,但在模型已被锁定并用于初始化上下文之前。”

    此外,如果您使用的是 EF6,则可以在域对象中声明关系,而不必自己手动声明关系。我看到您已经在模型中声明了关系;删除它,看看会发生什么。有关配置一对多关系的更多信息,请参阅here

    【讨论】:

    • 您好伊万,感谢您的回复!我之前确实尝试过并删除了它,或者只是提交了它,但我仍然遇到同样的错误。
    • 我应该提到我在 OnModelingCreating 中取出了一些行,以查看是否是导致问题的违规代码,但没有任何乐趣。
    【解决方案3】:

    可能是连接字符串或其他与连接相关的问题,例如数据库不存在或身份验证。

    您可能还需要更新数据库。

    从 nuget 包管理器控制台:

    Update-Database
    

    "Context cannot be used while the model is being created" exception with ASP.NET Identity

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

    The context cannot be used while the model is being created

    【讨论】:

      猜你喜欢
      • 2016-01-13
      • 2016-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-20
      • 2014-02-16
      相关资源
      最近更新 更多