简体   繁体   中英

Entity framework and ASP.NET Identity

Using ASP.NET MVC 5 and Entity Framework 6, I am trying to save a new record Package to the database. I have the following model entities:

User.cs ( ApplicationUser in the default template)

public class User : IdentityUser
{
    private ICollection<Package> packages;

    public User()
    {
        this.packages = new HashSet<Package>();
    }

    public virtual ICollection<Package> Packages
    {
        get { return this.packages; }
        set { this.packages = value; }
    }

    ...
}

Package.cs

public class Package
{
    private ICollection<User> maintainers;

    public Package()
    {
        this.maintainers = new HashSet<User>();
    }

    [Required]
    public virtual ICollection<User> Maintainers
    {
        get
        {
            return this.maintainers;
        }

        set
        {
            this.maintainers = value;
        }
    }

    ...
}

I have the following DbContext class:

public class ApplicationDbContext : IdentityDbContext<User>, IApplicationDbContext
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public virtual IDbSet<Package> Packages { get; set; }

    ...

    public static ApplicationDbContextCreate()
    {
        return new ApplicationDbContext();
    }
}

I also have PackageService.cs (similar to the service pattern):

public class PackagesService : IPackagesService
{
    private readonly IRepository<Package> packages;

    public PackagesService(IRepository<Package> packages)
    {
        this.packages = packages;
    }


    public Package Create(IList<User> maintainers)
    {
        var newPackage = new Package
        {
            Maintainers = maintainers
        };

        this.packages.Add(newPackage);
        this.packages.SaveChanges();

        return newPackage;
    }
}

I also have standard implementation of IRepository as a GenericRepository: source code here .

Now the problem I'm having is that when the Create() method is called Entity Framework throws the following exception:

An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code

Additional information: An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

I understand that the problem is that the Package entity is change-tracked by two different DbContexts, but I use the same ApplicationDbContext through the entire application. Moreover, here's how I inject it (using Ninject):

kernel.Bind<DbContext>().To<ApplicationDbContext>().InRequestScope();
kernel.Bind(typeof(IRepository<>)).To(typeof(GenericRepository<>));
kernel.Bind<IUserStore<User>>().To<UserStore<User>>().WithConstructorArgument("context", kernel.Get<DbContext>());
kernel.Bind<UserManager<User>>().ToSelf();

This is the part that confuses me the most. Not only do I bind the context with Ninject, but wherever I use ie UserManager , I get it through the Owin instance, which creates it with the Create() static method of exactly the same DbContext. So how could there be two DbContext instances?

I've spent the whole day debugging this and I can't understand why it's happening. Thanks in advance.

I'm not sure whether the problem was the DI bindings and Ninject in particular, but I managed to find a workaround. Since apparently I had two instances of a DbContext, instead of using the records from the first one I mapped the many-to-many relationship with the primary keys only. Something along the following lines:

if (maintainerIds != null && maintainerIds.Count > 0)
{
    foreach (string maintainerId in maintainerIds)
    {
        var maintainer = new User() { Id = maintainerId };
        users.Attach(maintainer);
        newPackage.Maintainers.Add(maintainer);
    }
}

This basically doesn't even require a DbContext as long as the ids match.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM