EF6 MVC5 and Visual Studio 2017 Code First Database

I am working on EF6 with MVC5.
The solution is a job manager application.
Here are the data classes

Job class
      Description
      AddressLine1..3
      City
      State
      Zip
      ContractId
      Contract

Contract class
      ContractDescription
      RecruiterID
      RecruitingCompanyID
      RecruitingCompany
      Job


RecruitingCompany class
      CompanyName
      AddressLine1..3
      City
      State
      Zip
      Phone
      ICollection<RecruiterContact>RecruiterContact
      ICollection<Contract>Contracts

RecruiterContact class
      FirstName
      LastName
      RecruitingCompanyID
      RecruitingCompany


The relations need to be as follows:
Job to Contract is 1 to 1
Contract to RecruitingCompany is 1 to 1
RecruitingCompany to Contract is 1 to Many
RecruitingCompany to RecruiterContact is 1 to Many

So,  I will speak to a reqruiter, potentially add the recruiter to the recruiter company or just add to an existing in the DB recruiter company.  The reqruiter gets the contract and the contract is tied to the job.  I think this models the process, but how to build the classes such that EF will build the database/tables/keys/foreign keys and then bootstrapping with some test data is my challenge.

Any suggestions for the data/entity classes and the subsequent bootstrap data would be appreciated.
LVL 1
Howard BashSenior Software EngineerAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Fernando SotoRetiredCommented:
Hi Howard;

Please see this web page Relationship in Entity Framework Using Code First Approach With Fluent API which should answer your questions and in detail.
0
Howard BashSenior Software EngineerAuthor Commented:
I don't think you have to use fluent though.  Also I am not using core.  I am using EF6 Net.
0
Howard BashSenior Software EngineerAuthor Commented:
I thought I'd back up a bit and create a simplier solution using MVC and EF.  I created a MVC5 solution, installed EF6 using PMC.  I added a class Job that is as follows:
    
public class Job
    {
        public int JobID { get; set; }
        public Boolean Active { get; set; }

        [Required()]
        [StringLength(100, MinimumLength = 5)]
        public string Description { get; set; }

        public string AddressLine1 { get; set; }
        public string AddressLine2 { get; set; }
        public string AddressLine3 { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string ZipCode { get; set; }

        [Required()]
        public string PhoneNumber { get; set; }

        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
    }

Open in new window


I then created a DAL folder and added a JobsDBContext class as follows:
    public class JobsDBContext : DbContext
    {

        public JobsDBContext() : base("JobsDBContext")
        {
        }

        public DbSet<Job> Jobs { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            //            base.OnModelCreating(modelBuilder);
        }


    }

Open in new window


And then added a JobjsInitializer class as follows:
 public class JobsInitializer : System.Data.Entity.DropCreateDatabaseIfModelChanges<JobsDBContext>
    {
        protected override void Seed(JobsDBContext context)
        {

            base.Seed(context);
        }
    }

Open in new window


After all that I ran the following command in the PMC:
Enable-Migrations -ContextTypeName JobHandler.DAL.JobsInitializer -MigrationsDirectory Migrations

That command created the Migrations folder and a Configuration.cs file, but has some trouble compiling the project with the two classes created and listed above (in the DAL folder).

The configuration class within the new Migrations folder follows:
    internal sealed class Configuration : DbMigrationsConfiguration<JobHandler.DAL.JobsInitializer>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            MigrationsDirectory = @"Migrations";
        }

        protected override void Seed(JobHandler.DAL.JobsInitializer context)
        {
            //  This method will be called after migrating to the latest version.

            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data.
        }
    }

Open in new window


The Configuration class name as a squiggly where the error is.  

The type JobHandler.DAL.JobsInitializer cannot be as a type parameter 'TContext'  in the generic type or method 'DbMigrationsConfiguration<TContext>'.  There is no implicit reference conversion from JobHandler.DAL.JobsInitializer to System.Data.Entity.DbContext.

I don't see why this is as the classes appear to me to be correctly defined.
0
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

Howard BashSenior Software EngineerAuthor Commented:
There are one or two typos above, but I don't see an edit option to correct...
0
Fernando SotoRetiredCommented:
To the original question in this thread please see the tutorial Getting Started with Entity Framework 6 Code First using MVC 5 which uses the minimum versions VS 2013, .Net 4.5 and EF6.

Can you please zip up the simpler version and post it somewhere so I can download it to see what the issue is.
0
Fernando SotoRetiredCommented:
To your post, "There are one or two typos above, but I don't see an edit option to correct...", if you bring your mouse pointer to the upper right of the post you will see 3 vertical dots inside a square appear click on it which will give you an option to edit the post. This can only be done to the last post in the thread only. See image below.How to edit last post
0
Howard BashSenior Software EngineerAuthor Commented:
Still struggling with creating the model classes such that I can add-migration SomeName and then update-database...

I have backed off of that for a few to work on the bits that I can.  At the moment I can add and delete rows for jobs table and a contracts table.  But, the edit and save fails.  I have included the job piece and the error here:

	[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "ID,Active,Description,AddressLine1,AddressLine2,AddressLine3,City,State,ZipCode,PhoneNumber,StartDate,EndDate")] Job job)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    db.Entry(job).State = EntityState.Modified;
                    db.SaveChanges();
                }
                catch (DbUpdateConcurrencyException ex)
                {
                    //var entry = ex.Entries.Single();
                    //var currentValues = entry.CurrentValues;
                    //var databaseValues = entry.GetDatabaseValues();
                    ex.Entries.Single().Reload();
                }

                return RedirectToAction("Index");
            }
            return View(job);
        }

Open in new window


And the save changes method throws a DBUpdateConcurrencyException.  Here is the error's message:
"Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions."
0
Fernando SotoRetiredCommented:
Hi Howard;

Each question posted on EE should only target one issue/question. If you have more then one question there should be one thread for each. From my understanding of the original question you need understanding of building relationships which is shown in my last link posted. Please go through that tutorial which goes step by step which covers what you need.
0
Howard BashSenior Software EngineerAuthor Commented:
I have gone through both links and built the solutions they work through.  However,  I still cannot get my version to seed a one to many relation (recruiting company to contracts).  I have included these two classes as well as the seed method with it's error.

    public class RecruitingCompany
    {
        public int RecruitingCompanyID { get; set; }
        public Boolean Active { get; set; }

        [Required()]
        [StringLength(100, MinimumLength = 5)]
        public string CompanyName { get; set; }

        public string AddressLine1 { get; set; }
        public string AddressLine2 { get; set; }
        public string AddressLine3 { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string ZipCode { get; set; }

        [Required()]
        public string PhoneNumber { get; set; }

        public List <Contract> Contracts { get; set; }
    }

    public class Contract
    {
        public int ContractID { get; set; }
        public string ContractDescription { get; set; }
        public Boolean Active { get; set; }

         public RecruitingCompany RecruitingCompany { get; set; }

    }

Open in new window


protected override void Seed(JobHandler.DAL.JobsDBContext context)
        {
            RecruitingCompany rc = new RecruitingCompany()
            {
                Active = true,
                CompanyName = "Q & C Software",
                AddressLine1 = "123 Main Street",
                AddressLine2 = "Suite 199",
                AddressLine3 = "",
                City = "Baltimore",
                State = "Maryland",
                ZipCode = "12345",
                PhoneNumber="718-999-1111",
                Contracts = {
                    new Contract()
                    {
                        Active=true,
                        ContractDescription="FishHead Consulting House"
                    },
                    new Contract()
                    {
                        Active=true,
                        ContractDescription="Bozo Land Consulting"
                    },
                    new Contract()
                    {
                        Active=true,
                        ContractDescription="Rhipe Solutions"
                    }
                }

            };
            context.RecruitingCompanies.Add(rc);
            context.SaveChanges();
        }

Open in new window


My RecruitingCompany Detail View when I did seed the tables (one iteration of the code that differs from the included) looks like this and gets an error that there is no contracts object to iterate through whereas the db shows the records.
@model JobHandler.Models.RecruitingCompany

@{
    ViewBag.Title = "Details";
}

<h2>Details</h2>

<div>
    <h4>RecruitingCompany</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.Active)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Active)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.CompanyName)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.CompanyName)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.AddressLine1)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.AddressLine1)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.AddressLine2)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.AddressLine2)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.AddressLine3)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.AddressLine3)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.City)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.City)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.State)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.State)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.ZipCode)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.ZipCode)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.PhoneNumber)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.PhoneNumber)
        </dd>

    </dl>
</div>

<ul>
    @foreach (var contract in Model.Contracts)
    {
        <li>@contract.ContractDescription</li>
    }
</ul>

<p>
    @Html.ActionLink("Edit", "Edit", new { id = Model.RecruitingCompanyID }) |
    @Html.ActionLink("Back to List", "Index")
</p>

Open in new window



When I run update-database from the PMC, I get this error:
Object reference not set to an instance of an object.
0
Fernando SotoRetiredCommented:
OK Howard, in your last post you had an error in your seeding code. The Contract class does not have a collection instantiated for Contracts in the class and so it needs to be done in the seeding code. Please try the below code in place of yours.
RecruitingCompany rc = new RecruitingCompany()
{
    Active = true,
    CompanyName = "Q & C Software",
    AddressLine1 = "123 Main Street",
    AddressLine2 = "Suite 199",
    AddressLine3 = "",
    City = "Baltimore",
    State = "Maryland",
    ZipCode = "12345",
    PhoneNumber = "718-999-1111",
    Contracts = new List<Contract>()
    { 
        new Contract()
        {
            Active = true,
            ContractDescription = "FishHead Consulting House"
        },
        new Contract()
        {
            Active = true,
            ContractDescription = "Bozo Land Consulting"
        },
        new Contract()
        {
            Active = true,
            ContractDescription = "Rhipe Solutions"
        }
    }
};

Open in new window

0
Howard BashSenior Software EngineerAuthor Commented:
Hi,
I made the change to the seed method and built the migration and added the data.  I deleted the previous data in the two tables to make sure I was only using the new data.

However, the details method still fails.

Here is the Seed Method:
        protected override void Seed(JobHandler.DAL.JobsDBContext context)
        {
            RecruitingCompany rc = new RecruitingCompany()
            {
                Active = true,
                CompanyName = "M & B Software",
                AddressLine1 = "123 Main Street",
                AddressLine2 = "Suite 199",
                AddressLine3 = "",
                City = "Baltimore",
                State = "Maryland",
                ZipCode = "12345",
                PhoneNumber="718-767-2225",
                Contracts = new List<Contract>(){
                    new Contract()
                    {
                        Active=true,
                        ContractDescription="FishHead Consulting House"
                    },
                    new Contract()
                    {
                        Active=true,
                        ContractDescription="Bozo Land Consulting"
                    },
                    new Contract()
                    {
                        Active=true,
                        ContractDescription="Rhipe Solutions"
                    }
                }

            };

            context.RecruitingCompanies.Add(rc);
            context.SaveChanges();
        }

Open in new window


Here is the data in the tables
Rec to contracts
Here is the Detail Razor code (errors on the contract in model.Contracts section
@model JobHandler.Models.RecruitingCompany

@{
    ViewBag.Title = "Details";
}

<h2>Recruiting Company Details</h2>

<div>
    <h4>RecruitingCompany</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.Active)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Active)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.CompanyName)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.CompanyName)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.AddressLine1)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.AddressLine1)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.AddressLine2)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.AddressLine2)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.AddressLine3)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.AddressLine3)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.City)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.City)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.State)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.State)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.ZipCode)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.ZipCode)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.PhoneNumber)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.PhoneNumber)
        </dd>

    </dl>
</div>

<ul>
    
    @foreach (var contract in Model.Contracts)
    {
        <li>@contract.ContractDescription</li>
    }
</ul>

<p>
    @Html.ActionLink("Edit", "Edit", new { id = Model.RecruitingCompanyID }) |
    @Html.ActionLink("Back to List", "Index")
</p>

Open in new window


Here is the error:
Err
0
Fernando SotoRetiredCommented:
Can you zip the project up and place it on the web where I can download it and run it on my system, please.
0
Howard BashSenior Software EngineerAuthor Commented:
The zipped file is 53mb.  Can I delete the bin folder contents and the packages folder contents?
0
Fernando SotoRetiredCommented:
Yes.
0
Howard BashSenior Software EngineerAuthor Commented:
0
Fernando SotoRetiredCommented:
When you start the app what page do you go to?
0
Howard BashSenior Software EngineerAuthor Commented:
Could go to the home page.  After that, click on jobs at top menu, and then details.
0
Fernando SotoRetiredCommented:
When I run the app it displays the standard ASP.Net home page with the link in the upper left that states "Application name ". Is that what I need to click on?
0
Howard BashSenior Software EngineerAuthor Commented:
Click on Jobs and then details
0
Howard BashSenior Software EngineerAuthor Commented:
My error.  Click on recruiting company and then details.  That will take you to the exception
0
Fernando SotoRetiredCommented:
You do not have the seed data set in the project. Please correct and also change database initialization strategy to "DropCreateDatabaseAlways" at least until you get pass this issue. Then repost the updated project to the web.
0
Howard BashSenior Software EngineerAuthor Commented:
Not sure about how to wire the DropCreateDatabaseAlways in.  Regarding the data,  I thought that when I enable-migrations in the PMC and then Add-Migration "SomeName" and then do an update-database, my configuration.cs runs and that data within it's seed method runs.  I think that is the case as data from that seed method does show in the database and also the recruiting company record and contracts show up.

I think an issue there is that once I started using migrations, using initializers became another issue.  So,  my seed is in the configuration.cs file as this time. (Still learning EF)
0
Fernando SotoRetiredCommented:
It does not seem to be with the project you posted. Also seed data is missing.
0
Howard BashSenior Software EngineerAuthor Commented:
In the migrations folder is configuration.cs.  If you run update-database in the PMC, you should get the data loaded.
0
Fernando SotoRetiredCommented:
The issue now is the loading of related entities from the database by default related data is not loaded so the way you have the model configured you will need to tell EF to load the related records as well. To do that change this line in your RecruitingCompanyController from this in the Details method from this
RecruitingCompany rc = db.RecruitingCompanies.Find(id);

Open in new window

to this
RecruitingCompany rc = db.RecruitingCompanies.Include(r => r.Contracts).Where(r => r.RecruitingCompanyID == id).FirstOrDefault();

Open in new window

In order for that change to work you will need to add this using statement.
using System.Data.Entity;

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Howard BashSenior Software EngineerAuthor Commented:
Excellent!  Worked like a charm.  I would like to continue discussing this project as a new question.
0
Howard BashSenior Software EngineerAuthor Commented:
Great help.  Very knowledgeable and patient with a EF nubie.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Databases

From novice to tech pro — start learning today.