我正在使用ASP.NET MVC应用程序,该应用程序基于可通过NuGet获得的Identity示例。因此,我已经有一些类可以与数据库一起使用,例如ApplicationDbContext。
说,我决定让用户将请求留给管理员。我已经将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>()));
}
但是我没有任何商店可以满足我的要求,所以我不知道我应该对“新RoleStore”部分做什么。我该如何解决这个问题?
更新:
我已经尝试过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()会导致什么问题。我是否应该使用它,因为它比添加外键更简单?
设计的麻烦在于每个经理都有自己的环境。看这个例子,我想每个经理都应该打电话给...
db = context.Get<ApplicationDbContext>();
...或在其构造函数中接收受请求限制的上下文。
除此之外,您还可以通过将异域作为ApplicationUser
(ApplicationUserId
?)的原始属性公开给Request
:
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; }
}
然后Request
像这样创建:
var userId = User.Identity.GetUserId();
Request request = new Request
{
Message = model.Message,
ApplicationUserId = userId
};
与仅具有参考导航属性的独立关联相反,这称为外键关联。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句