【问题标题】:Entity framework and ASP.NET Identity实体框架和 ASP.NET 标识
【发布时间】:2016-02-05 21:50:30
【问题描述】:

使用 ASP.NET MVC 5 和 Entity Framework 6,我正在尝试将新记录 Package 保存到数据库中。我有以下模型实体:

User.cs(默认模板中的ApplicationUser

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

我有以下 DbContext 类:

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

我也有 PackageService.cs(类似于服务模式):

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

我也有 IRepository 作为 GenericRepository 的标准实现:source code here

现在我遇到的问题是,当调用 Create() 方法时,Entity Framework 会抛出以下异常:

EntityFramework.dll 中出现“System.InvalidOperationException”类型的异常,但未在用户代码中处理

附加信息:一个实体对象不能被多个 IEntityChangeTracker 实例引用。

我知道问题在于 Package 实体由两个不同的 DbContexts 进行更改跟踪,但我在整个应用程序中使用相同的 ApplicationDbContext。此外,这是我注入它的方式(使用 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();

这是最让我困惑的部分。我不仅将上下文与 Ninject 绑定,而且无论在哪里使用,即UserManager,我都通过 Owin 实例获取它,该实例使用完全相同的 DbContext 的 Create() 静态方法创建它。那么怎么会有两个 DbContext 实例呢?

我花了一整天的时间来调试这个,我不明白为什么会这样。提前致谢。

【问题讨论】:

  • 你的类定义说ApplicationDbContext,但是在你的ninject配置kernel.Bind&lt;DbContext&gt;().To&lt;LinuxPackagesDbContext&gt;().InRequestScope();你能澄清一下吗
  • 已修复,复制粘贴出错。
  • @arnaudoff 也许删除问题或在答案中写下问题所在
  • 当您通过维护者public Package Create(IList&lt;User&gt; maintainers) 时,它是否可能来自另一个上下文?尝试注释掉Maintainers = maintainers 看看是否是问题所在。至少这可以帮助你缩小范围
  • @b1tsh1ft,好吧,删除该行似乎可以解决问题,但这并不能解决问题。维护者来自this.UserManager.Users,其中UserManager 属性与创建新项目时出现的默认MVC 模板中来自ManageController.cs 的属性完全相同,因此从Owin 管道获取上下文。

标签: c# asp.net .net asp.net-mvc entity-framework


【解决方案1】:

我不确定问题是否出在 DI 绑定和 Ninject 上,但我设法找到了解决方法。因为显然我有两个 DbContext 实例,而不是使用第一个实例中的记录,我只映射了与主键的多对多关系。大致如下:

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

只要 id 匹配,这基本上甚至不需要 DbContext。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 2017-01-06
    • 2011-02-20
    • 2010-10-07
    • 2015-05-20
    相关资源
    最近更新 更多