8

I'm a bit new when it is coming to Entity Framework 6 from the old style of ADO.NET, so bear with me here.

I'm trying to create a new WPF MVVM project and also a few WinForms that will use just straight out DBContext without data-binding with the EF 6.

Using Visual Studio 2013 Entity framework wizard, I created a code-first by reverse engineer a current database on our business server. I then separated the data model classes from the context

This is the DbContext code:

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

I've separated the data classes in a separate namespace, for example:

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

The rest of the classes are in similiar style, but when using the foreign key constraint it has something like this:

public virtual OrderDetail OrderDetail { get; set; }

since in our little world, it will revolve around the Orders.

And the 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>

So when I do this:

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

An exception is thrown:

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.

I'm going nuts here trying to figure out what I can do, and I've been reading that maybe doing a task factory could help, so then how can I use it to get the data from each table so I can populate the lists?

OR is there another alternative or a workaround that I can use?

EDIT: Here is the FULL stacktrace as requested (by 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)
Dan Homola
  • 3,819
  • 1
  • 28
  • 43
Steve Brother
  • 838
  • 2
  • 11
  • 21
  • Ideally you need to wrap the context in a using statement: using (var context = new MyDataContext() { var list1 = context.JournalEntryDatas.ToList(); var list2 = context.OrderHistories.ToList(); } But I can't see this being the cause. – Andez Aug 20 '15 at 22:11
  • I am assuming the model is all valid including the relations defined in the model builder? Have you tried starting with fewer model classes (say two) and work it out from there? Also have- you got a call stack of the exception? Also check you haven't got any async calls happening in code that might be omitted from your post. – Andez Aug 20 '15 at 22:19
  • 1
    normally this happens with multi threaded code and accessing the context while its first instantiated and already building the model from another thread. You just have those three lines running? – kmcc049 Aug 20 '15 at 23:43
  • Sorry Andez, I just put the entire stacktrace into the question since I wasn't able to place it here in the comments. I hope that can help you out a bit in helping me solve this issue – Steve Brother Aug 21 '15 at 18:30
  • @kmcc049: I was thinking the same thing, but I'm just running one UserControl because I need to test it out. It does raise the question on how I can encapsulate the DbContext to make it thread-safe. Hence why I was asking about TPL or Task Factory. I seen other people using WebAPI having the same issue I am, but I'm using this in a WinForm and WPF. I just don't know how to use either one of those methods... yet! :-) – Steve Brother Aug 21 '15 at 18:41
  • @kmcc049: I did forget to mention that I'm going to place this into a repository so any other usercontrols I develop will go to one place, but I want to make sure that UserControl1 will not fail when UserControl2 also needs to access the data. Any ideas? – Steve Brother Aug 21 '15 at 18:45
  • *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.* The context isn't used inside `OnModelCreating`, you must be using one context instance in multiple threads simultaneously, somewhere. – Gert Arnold Jul 29 '16 at 14:17
  • I'm not entirely sure if this is your problem, but I see you call context.JournalEntryDatas.ToList(). However, this DbSet doesn't exist on your DbContext. Are you showing us everything in the DbContext or else how are you calling that? – Daniel Lorenz Feb 12 '18 at 02:36
  • I hope [this] answer(https://softwareengineering.stackexchange.com/questions/229949/how-to-handle-field-level-acces-security-when-using-entity-framework/361755#361755) will help you. – JohnyL May 15 '18 at 18:35
  • I hope that [this](https://softwareengineering.stackexchange.com/questions/229949/how-to-handle-field-level-acces-security-when-using-entity-framework/361755#361755) answer will help you. – JohnyL May 15 '18 at 18:39

3 Answers3

1

You said you (were) new to entity framework, so perhaps it is worth pointing out that DbContexts are not supposed to be shared and reused. Usually you'll want to create, use, and dispose a DbContext within a single unit of work.

In other words, you shouldn't be "sharing" the DbContext (e.g. creating just one at startup and using it in multiple places, etc. You mentioned trying to create a "thread-safe wrapper" -- you definitely shouldn't be trying to access it from multiple threads (each operation would have its own DbContext)

CodeNotFound
  • 22,153
  • 10
  • 68
  • 69
Mark Sowul
  • 10,244
  • 1
  • 45
  • 51
0

I think it might have to do with the foreign key creation in onModelCreating. According to the documentation, the onMethodCreating method "is called when the model for a derived context has been initialized, but before the model has been locked down and used to initialize the context."

Besides, if you're using EF6, you can declare the relationship in your domain objects instead of having to manually declare the relationship yourself. I'm seeing that you already have the relationships declared in your model; remove that and see what happens. See here for more info on configuring one-to-many relationships.

Ivan Peng
  • 579
  • 5
  • 16
  • Hi Ivan, thanks for the response! I did try that before and removed, or just committed it out, and I'm still getting the same error. – Steve Brother Aug 21 '15 at 18:32
  • I should have mentioned that I took out some lines inside the OnModelingCreating to see if it was offending code that is causing the problem, but no joy. – Steve Brother Aug 21 '15 at 18:39
0

It might be the connection string or some other connection-related issue, the database not existing or authentication for example.

You might need to update the database as well.

From the nuget package manager console:

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

Community
  • 1
  • 1
Charlie
  • 8,530
  • 2
  • 55
  • 53