【问题标题】:How to update entity related with ApplicationUser using EF6?如何使用 EF6 更新与 ApplicationUser 相关的实体?
【发布时间】:2017-09-06 00:59:17
【问题描述】:

我在 ASP.NET MVC 中更新与应用程序用户相关的实体时遇到问题。我在ApplicationUserOrder 之间有一对多的关系。这是我的实体和关系配置:

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<Order> HandlingOrders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    //some properties

    public string OperatorId { get; set; }
    [ForeignKey("OperatorId")]
    public virtual ApplicationUser Operator { get; set; }
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.Entity<ApplicationUser>().HasMany(n => n.HandlingOrders)
                                          .WithOptional(n => n.Operator)
                                          .HasForeignKey(n => n.OperatorId);
}

问题是,当我尝试将Order 保存在我的控制器中时,它会失败并显示InvalidOperationException 和消息

无法定义两个对象之间的关系,因为它们附加到不同的 ObjectContext 对象。

这是因为一方面我使用“工作单元”和“通用存储库”来保存Order。另一方面,我使用ApplicationUserManager 保存ApplicationUser

public class OperatorController : Controller
{
    private readonly UnitOfWork _unitOfWork;

    private ApplicationUserManager _userManager
    {
        get { return HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
    }
}

结果我得到两个上下文:第一个是来自GetOwinContext()IOwinContext,第二个是我的常规ApplicationContext,在“工作单元”中创建(或正在创建?)。并且这种上下文会导致异常。

谁能建议我,在这种情况下什么是最好的?我为ApplicationUser写repository而奋斗,但我从未在文章中看到过这样的做法,所以我不确定。

【问题讨论】:

  • 从显而易见的开始。 ApplicationUser 是否在一个上下文中(如默认的 IdentityDbContext),Order 是否在另一个上下文中声明,如 ApplicationContext?那会导致你的错误。如果是这样,只需让您的 ApplicationContext 继承自 IdentityDbContext。
  • @SteveGreene 不,我的ApplicationContext 已经继承自IdentityDbContext&lt;TUser&gt;。实际上,我有一个上下文的两个实例是通过两种不同的方式创建的,这会导致错误。问题是我不知道如何与没有ApplicationUserManager 的用户合作,据我所知,无法使用ApplicationContext 进行初始化。
  • 如果您只是引用用户,则不需要 UserManager。例如,ApplicationUser myUser = context.Users.FirstOrDefault(u =&gt; u.Id == myUserId); 将获取身份用户。如果您要更改密码等,则需要 UserManager。显示相关的存储库代码。
  • @SteveGreene 它应该类似于that,我认为(最后三个方法中的存根是,因为类必须实现接口)。这应该可以工作,直到我不必更改用户中的某些内容:)

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


【解决方案1】:

第一种方式解释: 根据您的错误信息,据我所知,可能是您更改了上下文的结构,但可以更新数据库,所以我建议您在保存之前需要更新数据库。

您可以使用数据库迁移命令来更新数据库而不更改您拥有的数据,如下所示: 转到工具 -> 库包管理器 -> 包管理器控制台, 在包管理器控制台中运行 Enable-Migrations 命令, 添加迁移, 更新数据库, 添加迁移(您的项目)

第二种解释方式: IOwinContext 接口:它包装了 OWIN 环境字典并提供强类型访问器。 GetOwinContext 与 HttpContext 的接口:获取当前请求的 IOwinContext。 GetOwinContext 与 Http 请求的接口:获取当前请求的 IOwinContext。 在ApplicationContext的情况下,我们可以这样使用:

Public ApplicationContext:DbContext
{
Public ApplicationContext():base(“ConnectionStringName”)
{
Database.SetInitializer<ApplicationContext>(null);
}
//Dbsets here
}

当我们试图在这种情况下保存不同的订单时,我们可以使用第二种方案,例如通过存储库模式的工作单元。它也是一种将数据从一个框架传输到另一个框架的灵活方式。

【讨论】:

  • 第一种方式:不,我没有更改我的实体。可以肯定的是,我运行“Add-Migration”并生成空的Up()Down()。第二种方式:我已经使用过这样的上下文,而且DbContext 不适合具有个人用户身份验证的应用程序。必须使用 IdentityDbContext&lt;TUser&gt; 而不是它。
  • 如果上下文结构发生变化,则消息为:“支持 'ContextName' 上下文的模型在创建数据库后发生了变化。考虑使用代码优先迁移来更新数据库”
  • 这个答案没有意义。问题是您有 2 个上下文进行一次更新,而不是您的模型不同步。
猜你喜欢
  • 2015-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-15
  • 1970-01-01
相关资源
最近更新 更多