2

型ごとのテーブル継承の使用Landlordから継承するクラスがあります。UserProfile

新しいユーザーがアプリケーションに登録するとき、ユーザーはいくつかの基準を入力し、必要なアカウントのタイプを選択しLandlordますTenant

これが私のAccountController/Registerメソッドです。

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追加します。たとえば、aは1です。UserProfileUserProfileId

次に、if (model.AccountType == AccountType.Tenant)選択したアカウントの種類がTenantであることがわかります。ユーザーをその役割に追加します。aUserProfileIdは1、aRoleIdは1です。この中if-statementで、選択した役割はであるため、次のようTenantに新しいものを作成します。データベースに保存されます( PKとして正しいUserProfileIDを使用)。Tenantvar tenant = db.UserProfile.Create<Tenant>();

問題:1人のユーザーを登録しようとするたびに、2つのUserProfileエンティティ(2行)がテーブルに追加されます。UserProfileこれはおそらく、私が呼び出しているという事実とWebSecurity.CreateUserAndAccount、新しいTenantオブジェクトを作成していることが原因であると理解しています。

この状況を回避するにはどうすればよいですか?

WebSecurity.CreateUserAndAccount使用しているモデルをUserProfileテーブルとテーブルに一度追加するにはどうすればよいTenantですか?

4

2 に答える 2

2

UserProfileサブクラスTenentまたはLandlordをそれぞれ呼び出しWebSecurity.CreateUserAndAccount()て作成し、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; }
}

AccountController / Registerメソッドの場合:

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));
            }
        }
于 2013-03-22T11:17:58.133 に答える
1

この場合、UserProfile と Tenant または Landlord の両方を作成することはありません。エンティティが作成されると、エンティティ タイプを変更することはできません (サブタイプに拡張する場合でも)。したがって、あなたの場合、 UserProfile を作成するステップをスキップして、それを継承する Tenant または Landlord エンティティを作成して保存するだけで済みます。

この質問に対する私の回答のオプション 1 からリンクされている詳細情報: Code First TPT Inheritance - How can I supply the external key instead of EF creating the parent row for me?

于 2013-01-29T20:21:13.850 に答える