1

Closed

Code First: TPC with joins from base class to Identity ApplicationUser Fails

description

I have been moving code from EF 5 to a new project using EF 6 and AspNet Identity, and got the following error when trying to enable code first migrations:
"The referenced EntitySet 'Ad' for End 'Ad' could not be found in the containing EntityContainer."

I have a TCP inheritance with a base class (just one! - not the same issue as http://entityframework.codeplex.com/workitem/981) and I have narrowed it down to joining my abstract class ("Ad") to my users ("ApplicationUser") with one-to-many navigation properties. The code works on EF 5.

Simplified (but fully reproducing) code, based on a new MVC Web Application:

using Microsoft.AspNet.Identity.EntityFramework;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;

namespace WebApplication1.Models
{
 //You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
    //Can't enble this navigation property
    //public virtual ICollection<Ad> Ads { get; set; }
}
public abstract class Ad
{
    [Key]
    [DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)]
    public int AdID { get; set; }
    public string UserId { get; set; }
    public string Name { get; set; }

    //Can't enble this navigation property
    //public virtual ApplicationUser User { get; set; }
}
public class Boat : Ad
{
    public int Width { get; set; }
    public int Length { get; set; }

}
public class Equipment : Ad
{
    public string Description { get; set; }
    public int Price { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }

    public System.Data.Entity.DbSet<WebApplication1.Models.Ad> Ads { get; set; }
    public System.Data.Entity.DbSet<WebApplication1.Models.Boat> Boats { get; set; }
    public System.Data.Entity.DbSet<WebApplication1.Models.Equipment> Equipment { get; set; }

    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Boat>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Boats");
        });
        modelBuilder.Entity<Equipment>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Equipment");
        });
    }
}
}
Closed Nov 22, 2013 at 6:54 PM by Mugdhak
Verified fixed

comments

ajcvickers wrote Nov 5, 2013 at 7:18 PM

Notes for triage: confirmed that this still repros with latest code in master. The model works fine when using TPH. Validation errors are:

Stack trace:
[ModelValidationException: One or more validation errors were detected during model generation:

UserId: : There is no property with name 'UserId' defined in the type referred to by Role 'Ad'.
Ad: : The referenced EntitySet 'Ad' for End 'Ad' could not be found in the containing EntityContainer.
Ad: EntityType: EntitySet 'Ad' is based on type 'Ad' that has no keys defined.
]
   System.Data.Entity.Core.Metadata.Edm.EdmModel.Validate() +163
   System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo) +462
   System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection) +55
   System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext) +62
   System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input) +123
   System.Data.Entity.Internal.LazyInternalContext.InitializeContext() +611
   System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) +18
   System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() +53
   System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext() +15
   System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider() +38
   System.Linq.Queryable.Where(IQueryable`1 source, Expression`1 predicate) +63
   Microsoft.AspNet.Identity.EntityFramework.UserStore`1.FindByNameAsync(String userName) +616
   Microsoft.AspNet.Identity.<FindByNameAsync>d__d.MoveNext() +102
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   Microsoft.AspNet.Identity.<ValidateUserName>d__0.MoveNext() +417
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   Microsoft.AspNet.Identity.<ValidateAsync>d__4.MoveNext() +252
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   Microsoft.AspNet.Identity.<CreateAsync>d__0.MoveNext() +390
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   Microsoft.AspNet.Identity.<CreateAsync>d__10.MoveNext() +453
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +24
   Investigate1791.Controllers.<Register>d__8.MoveNext() in c:\Stuff\Investigate1791\Investigate1791\Controllers\AccountController.cs:82
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   lambda_method(Closure , Task ) +23
   System.Threading.Tasks.TaskHelpersExtensions.ThrowIfFaulted(Task task) +33
   System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult) +68
   System.Web.Mvc.Async.<>c__DisplayClass34.<BeginInvokeAsynchronousActionMethod>b__33(IAsyncResult asyncResult) +16
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
   System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3c() +50
   System.Web.Mvc.Async.<>c__DisplayClass45.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3e() +225
   System.Web.Mvc.Async.<>c__DisplayClass30.<BeginInvokeActionMethodWithFilters>b__2f(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
   System.Web.Mvc.Async.<>c__DisplayClass28.<BeginInvokeAction>b__19() +26
   System.Web.Mvc.Async.<>c__DisplayClass1e.<BeginInvokeAction>b__1b(IAsyncResult asyncResult) +100
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +39
   System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +28
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +29
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(IAsyncResult asyncResult, ProcessRequestState innerState) +21
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +31
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9514812
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

mrlund wrote Nov 7, 2013 at 5:45 AM

Should I take this as confirmation that this is a bug? Any suggestions for a workaround?

Best regards,

Martin

mrlund wrote Nov 12, 2013 at 2:58 PM

I'm kind of stuck here, and can't move forward until I know what to do about this issue. Do I really need to roll back to EF 5, rather than push my project forward?

Could we get a comment?

Best regards,

Martin

ajcvickers wrote Nov 12, 2013 at 6:15 PM

Notes for triage: This is a regression from EF5. The simplified repro is below. Note that the exception in this case is very similar to that reported in https://entityframework.codeplex.com/workitem/981 so it could be that the people reporting that they are hitting that issue as a regression could in fact be hitting this issue instead.
public class ApplicationUser
{
    public virtual string Id { get; set; }
    public virtual ICollection<Ad> Ads { get; set; }
}

public abstract class Ad
{
    public int AdID { get; set; }

    public string UserId { get; set; }
    public virtual ApplicationUser User { get; set; }
}

public class Boat : Ad
{
}

public class ApplicationDbContext : DbContext
{
    public DbSet<ApplicationUser> Users { get; set; }
    public DbSet<Ad> Ads { get; set; }
    public DbSet<Boat> Boats { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ApplicationUser>().ToTable("AspNetUsers");

        modelBuilder.Entity<Boat>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Boats");
        });
    }
}

class Program
{
    static void Main(string[] args)
    {
        using (var context = new ApplicationDbContext())
        {
            EdmxWriter.WriteEdmx(context, XmlWriter.Create(@"C:\Stuff\Repro1791_EF6.xml"));
        }
    }
}

ajcvickers wrote Nov 12, 2013 at 6:16 PM

@mrlund We are working through investigation of this issue hope to provide a fix or workaround as soon as possible.

Thanks,
Arthur

mrlund wrote Nov 15, 2013 at 7:26 AM

Tried updating first EF, then Identity, then all remaining packages to latest nightly, and the problem still repros. Any workaround in sight?

Regards,

Martin

ajcvickers wrote Nov 19, 2013 at 5:14 PM

Fixed in changeset 44bb939cc55fbbb5662e3a5be3453baf18f3d0bf

mrlund wrote Nov 19, 2013 at 6:00 PM

That's great - does that mean it'll be in the nightly build tomorrow, and if so I assume it's the EntityFramework nuget package?

Best regards,

Martin