Matthew Hudson
Matthew Hudson

Reputation: 1316

MVC 5 Scaffolding Code generation with an Inherited Entity causes System.Core already imported

I have used Entity Framework DB First approach to create my model. I spent many hours fighting with the EDMX to set up the inheritance correctly (0 errors). Then now when trying to create either an MVC 5 Controller w/ Views using EF, or add a View for the inheriting class I revieve this error:

There was an error running the selected code generator:

'There was an error in compilation of the type 'CostaPropertyServices.Models.PropertyInfoEntities'.

CS1703: An assembly with the same identity 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' has already been imported. Try removing one of the duplicate references.'

I have two classes: Person and Vendor. Vendors inherit from Persons, and add only an int ID field named PackageID.

EDMX Graphical representation of Person and Vendor entities

If anyone has any idea why I would really appreciate it. EF Inheritance seems to have been much more trouble than it's worth so far. Many Thanks.

Edit: Maybe I'm not supposed to be generating the views for inheriting entities? Or maybe I've not configured the inheritance correctly (Not set base to abstract?)


Person.cs

namespace CostaPropertyServices.Models
{
    using System;
    using System.Collections.Generic;

    public partial class Person
    {
        public int PersonID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public string Mobile { get; set; }
        public Nullable<System.DateTime> Created { get; set; }
        public Nullable<System.DateTime> Modified { get; set; }
        public Nullable<System.DateTime> Deleted { get; set; }
    }
}

Vendor.cs

namespace CostaPropertyServices.Models
{
    using System;
    using System.Collections.Generic;

    public partial class Vendor : Person
    {
        public int PackageID { get; set; }
    }
}

Upvotes: 3

Views: 2543

Answers (1)

Matthew Hudson
Matthew Hudson

Reputation: 1316

I've found a solution! Well, to let me add controllers and views for the entity at least. I'll describe it briefly for anyone who is stuck on this too, however I plan to come back and expand this answer as soon as time allows.

It so happens that scaffolding worked completely fine with non-inheriting entities, and my project didn't seem to contain any references to System.Core, let alone a duplicate one. This made me think it was a compatibility issue with inheritance and the default scaffold-er.

Steps to Fix:

  1. Install MVCScaffolding using NuGet.

    PM> Install-Package MvcScaffolding
    
  2. Run the following command via Package Manager Console

    PM> Scaffold Controller Vendor -Repository
    

    Edit: Pass -DbContextType [YourProjectEntities] to specify a DbContext to update rather than it creating a new one you probably don't want.

  3. Update methods in generated VendorRepository.cs to use Persons table and not (non-existant) Vendors table. Below was my result:

    public class VendorRepository : IVendorRepository
    {
        PropertyInfoEntities context = new PropertyInfoEntities();
    
        public IQueryable<Vendor> All
        {
            get { return context.Persons.OfType<Vendor>(); }
        }
    
        public IQueryable<Vendor> AllIncluding(params Expression<Func<Vendor, object>>[] includeProperties)
        {
            IQueryable<Vendor> query = context.Persons.OfType<Vendor>();
            foreach (var includeProperty in includeProperties) {
                query = query.Include(includeProperty);
            }
            return query;
        }
    
        public Vendor Find(int id)
        {
            return context.Persons.OfType<Vendor>().SingleOrDefault(v => v.PersonID == id);
        }
    
        public void InsertOrUpdate(Vendor vendor)
        {
            if (vendor.PersonID == default(int)) {
                // New entity
                context.Persons.Add(vendor);
            } else {
                // Existing entity
                context.Entry(vendor).State = System.Data.Entity.EntityState.Modified;
            }
        }
    
        public void Delete(int id)
        {
            var vendor = context.Persons.OfType<Vendor>().SingleOrDefault(v => v.PersonID == id);
            context.Persons.Remove(vendor);
        }
    
        public void Save()
        {
            context.SaveChanges();
        }
    
        public void Dispose() 
        {
            context.Dispose();
        }
    }
    
  4. Eureka!

NOTE: See this blog for standard usage, tips and customisation.

Upvotes: 2

Related Questions