在 Mvc 4 中使用每类型表继承将对象添加到数据库
本文关键字:继承 对象 添加 数据库 类型 Mvc | 更新日期: 2023-09-27 17:56:37
我有一个类Landlord
,它使用每类型表继承从UserProfile
继承。
当新用户在应用程序上注册时,他们会输入一些条件并选择他们想要的帐户类型,Landlord
或Tenant
。
这是我的帐户控制器/注册方法:
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password,
new
{
Email = model.Email,
FirstName = model.FirstName,
LastName = model.LastName,
AccountType = model.AccountType.ToString()
},
false);
// Add user to role that corresponds with selected account type
if (model.AccountType == AccountType.Tenant)
{
try
{
Roles.AddUserToRole(model.UserName, "Tenant");
using (var db = new LetLordContext())
{
var tenant = db.UserProfile.Create<Tenant>();
tenant.TenantAge = null;
tenant.TenantGroupMembers = null;
tenant.UserId = WebSecurity.CurrentUserId;
tenant.UserName = model.UserName;
// more properties associated with tenant
// ...
db.UserProfile.Add(tenant);
db.SaveChanges();
}
}
catch (ArgumentException e)
{
ModelState.AddModelError("Unable to add user to role", e);
}
}
if (model.AccountType == AccountType.Landlord)
{
try
{
Roles.AddUserToRole(model.UserName, "Landlord");
using (var db = new LetLordContext())
{
var landlord = db.UserProfile.Create<Landlord>();
// same idea as adding a tenant
}
}
catch (ArgumentException e)
{
ModelState.AddModelError("Unable to add user to role", e);
}
}
return RedirectToAction("Confirm", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
例如,如果我在注册时选择Tenant
作为所需的帐户类型,WebSecurity.CreateUserAndAccount
会正确地将用户添加到UserProfile
表中,例如UserProfileId
为 1。
然后,if (model.AccountType == AccountType.Tenant)
会看到所选帐户类型为 Tenant
,将用户添加到该角色,UserProfileId
为 1,RoleId
为 1。在此if-statement
中,由于所选角色是Tenant
,我创建了一个新Tenant
,如下所示:var tenant = db.UserProfile.Create<Tenant>();
并将其保存到数据库中(使用正确的用户配置文件ID作为PK)。
问题:每次我尝试注册一个用户时,都会将两个UserProfile
实体(两行)添加到UserProfile
表中。我知道这可能是因为我正在调用WebSecurity.CreateUserAndAccount
并且我正在创建一个新的Tenant
对象。
如何避免这种情况?
如何将WebSecurity.CreateUserAndAccount
中使用的模型添加到表中UserProfile
并Tenant
表一次?
与其分别调用WebSecurity.CreateUserAndAccount()
并创建 UserProfile 子类 Tenent 或 Landlord,这会导致 UserProfile 表中出现重复条目,不如只创建子类(也提供 UserProfile 的值),然后调用方法 WebSecurity.CreateAccount()
。
以下是我解决问题的方法(我的子类称为医生):
在 AccountModels 中,我使用每个类型表的继承添加了子句:
public class UsersContext : DbContext
{
public UsersContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<Physician> Physicians { get; set; }
}
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
[Table("Physicians")]
public class Physician : UserProfile
{
public Guid PhysicianGUID { get; set; }
public string Name { get; set; }
}
在帐户控制器/注册方法中:
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
using( UsersContext dbContext = new UsersContext()){
dbContext.Physicians.Add(new Physician { UserName = model.UserName, Name = "testDoctor", PhysicianGUID = Guid.NewGuid() });
dbContext.SaveChanges();
}
WebSecurity.CreateAccount(model.UserName, model.Password);
WebSecurity.Login(model.UserName, model.Password);
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
在这种情况下,您不会同时创建用户配置文件和租户或房东。创建实体后,无法更改实体类型(即使将其扩展到子类型)。因此,在您的情况下,您只需要跳过创建用户配置文件的步骤,只需创建并保存继承它的租户或房东实体。
更多信息链接自我对此问题的回答的选项 1:代码优先 TPT 继承 - 如何提供外键而不是 EF 为我创建父行?