【发布时间】:2014-12-21 22:31:20
【问题描述】:
我正在使用 ASP.NET MVC 应用程序,该应用程序基于通过 NuGet 提供的 Identity 示例。因此,我已经有一些类可以使用数据库,例如应用程序数据库上下文。
比如说,我决定让用户为管理员留下请求。我已将 Request 类添加到模型中:
public class Request
{
public int Id { get; set; }
public string Message { get; set; }
public ApplicationUser User { get; set; }
}
由于示例使用不同的管理器来处理用户、角色等,我决定在 Identity.config 文件中创建另一个名为 ApplicationRequestManager 的管理器(尽管我不确定这是一个好的做法)。
public class ApplicationRequestManager : IRequestManager
{
private ApplicationDbContext db = new ApplicationDbContext();
public void Add(Request request)
{
db.Requests.Add(request);
db.SaveChanges();
}
...
}
这个类使用 ApplicationDbContext 来处理数据库,并且有一些方法来创建一个请求,找到它等等。
我在 Manage 控制器中创建了一个负责发送请求的方法:
public ActionResult SendRequest(IndexViewModel model)
{
Request request = new Request { Message = model.Message, User = UserManager.FindById(User.Identity.GetUserId()) };
requestManager.Add(request);
return View();
}
调用此方法时,出现以下异常:
一个实体对象不能被多个 IEntityChangeTracker 实例引用
如果我理解正确,异常的原因是我使用一个 ApplicationDbContext 来获取用户 - 通过 UserManager 并且我使用另一个 ApplicationDbContext 来添加请求 - 通过 RequestManager,所以我的请求附加到两个上下文。据我所知,可以通过将相同的上下文传递给 UserManager 和 RequestManager 来避免此类错误。但是,UserManager 通过 OwinContext 与其他管理器一起获取其上下文:
// Configure the db context, user manager and role manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
我怎样才能让我自己的经理也遵循这种模式?我尝试使用 CreatePerOwinContext 方法,例如
app.CreatePerOwinContext<ApplicationRequestManager>(ApplicationRequestManager.Create);
我还尝试按照 RoleManager 示例实现 Create 方法
public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
{
return new ApplicationRoleManager(new RoleStore<ApplicationRole>(context.Get<ApplicationDbContext>()));
}
但是我的请求没有任何商店,所以我不知道应该如何处理“新角色商店”部分。我怎么能解决这个问题?
更新:
我已经尝试过 Gert 的解决方案,它奏效了:
public class Request
{
public int Id { get; set; }
public string Message { get; set; }
[ForeignKey("User")]
public int ApplicationUserId { get; set; }
public ApplicationUser User { get; set; }
}
var userId = User.Identity.GetUserId();
Request request = new Request
{
Message = model.Message,
ApplicationUserId = userId
};
我也厌倦了使用 HttpConext.Current.GetOwinContext().Get 方法的另一种方式。我在 ApplicationRequestMananger 中添加了以下行:
public ApplicationRequestManager()
{
this.db = HttpContext.Current.GetOwinContext().Get<ApplicationDbContext>();
}
它与原始的 Request 类一起工作得很好。
问题是,每种方式各有什么优缺点?我已经阅读了外键,并且我非常了解一般概念;但我真的不明白 'HttpContext.Current.GetOwinContext().Get()' 会导致什么问题。我应该使用它,因为它比添加外键更简单吗?
【问题讨论】:
标签: c# asp.net asp.net-mvc entity-framework asp.net-identity