【发布时间】: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