2016-03-28 12 views
0

この質問はすでに数回述べられていますが、これはビルドインIDモデルに関連しています。MVC ID - FOREIGN KEY制約と競合するINSERTステートメント

"Company"という名前のカスタムモデルを作成しました。新しいユーザーを登録する際には、会社名も選択したいと思います。

必要なデータをRegisterViewModelに追加し、ビューとフォームを必要に応じて表示します。私はすでにCompanyテーブルに2社をシードしていたので、値はnullであってはいけません。

// GET: /Account/Register 
    [AllowAnonymous] 
    public ActionResult Register() 
    { 
     ViewBag.CompanyID = new SelectList(db.Companies, "CompanyID", "Company_Name"); 
     return View(); 
    } 

    // 
    // POST: /Account/Register 
    [HttpPost] 
    [AllowAnonymous] 
    [ValidateAntiForgeryToken] 
    public async Task<ActionResult> Register(RegisterViewModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      var user = new ApplicationUser { UserName = model.Email, Email = model.Email, ApplicationUser_FirstName = model.ApplicationUser_FirstName, ApplicationUser_LastName = model.ApplicationUser_LastName, ApplicationUser_Company = model.ApplicationUser_Company }; 

       var result = await UserManager.CreateAsync(user, model.Password); <<<---- This is where the error occurs <<<--- 
       if (result.Succeeded) 
       { 
        await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); 

        return RedirectToAction("Index", "Home"); 
       } 
       AddErrors(result); 

     } 

     // If we got this far, something failed, redisplay form 
     return View(model); 
    } 

私も午前:私はすべての問題を見ることができないアカウントコントローラをチェック

The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.AspNetUsers_dbo.Companies_CompanyID". The conflict occurred in database "aspnet-ProjectMed-20160327120257", table "dbo.Companies", column 'CompanyID'. 
The statement has been terminated. 

:私は次のエラーを持つ新しいユーザを挿入するとき

public class RegisterViewModel 
{   
    ... Removed some irrelevant code ... 

    [Required(ErrorMessage = "You must select a company name.")] 
    [Display(Name = "Company")] 
    public int CompanyID { get; set; } 
    public virtual Company ApplicationUser_Company { get; set; } 

問題が発生しますSQLテーブルのコピー:

AspNetUsersテーブル:

CREATE TABLE [dbo].[AspNetUsers] (
    [Id]      NVARCHAR (128) NOT NULL, 
    [ApplicationUser_FirstName] NVARCHAR (50) NOT NULL, 
    [ApplicationUser_LastName] NVARCHAR (50) NOT NULL, 
    [CompanyID]     INT   NOT NULL, 
    [Email]      NVARCHAR (256) NULL, 
    [EmailConfirmed]   BIT   NOT NULL, 
    [PasswordHash]    NVARCHAR (MAX) NULL, 
    [SecurityStamp]    NVARCHAR (MAX) NULL, 
    [PhoneNumber]    NVARCHAR (MAX) NULL, 
    [PhoneNumberConfirmed]  BIT   NOT NULL, 
    [TwoFactorEnabled]   BIT   NOT NULL, 
    [LockoutEndDateUtc]   DATETIME  NULL, 
    [LockoutEnabled]   BIT   NOT NULL, 
    [AccessFailedCount]   INT   NOT NULL, 
    [UserName]     NVARCHAR (256) NOT NULL, 
    CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC), 
    CONSTRAINT [FK_dbo.AspNetUsers_dbo.Companies_CompanyID] FOREIGN KEY ([CompanyID]) REFERENCES [dbo].[Companies] ([CompanyID]) ON DELETE CASCADE 
); 

GO 
CREATE NONCLUSTERED INDEX [IX_CompanyID] 
    ON [dbo].[AspNetUsers]([CompanyID] ASC); 

GO 
CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex] 
    ON [dbo].[AspNetUsers]([UserName] ASC); 

会社テーブル:

CREATE TABLE [dbo].[Companies] (
    [CompanyID]   INT   IDENTITY (1, 1) NOT NULL, 
    [Company_Name]  NVARCHAR (50) NOT NULL, 
    [Company_Code]  NVARCHAR (9) NOT NULL, 
    [Company_Address1] NVARCHAR (100) NOT NULL, 
    [Company_Address2] NVARCHAR (100) NULL, 
    [Company_PostalCode] NVARCHAR (15) NOT NULL, 
    [Company_City]  NVARCHAR (50) NOT NULL, 
    [CountryID]   INT   NOT NULL, 
    [Company_CLOG]  BIT   NOT NULL, 
    [Company_SubAgent] BIT   NOT NULL, 
    CONSTRAINT [PK_dbo.Companies] PRIMARY KEY CLUSTERED ([CompanyID] ASC), 
    CONSTRAINT [FK_dbo.Companies_dbo.Countries_CountryID] FOREIGN KEY ([CountryID]) REFERENCES [dbo].[Countries] ([CountryID]) ON DELETE CASCADE 
); 


GO 
CREATE UNIQUE NONCLUSTERED INDEX [IX_Company_Code] 
    ON [dbo].[Companies]([Company_Code] ASC); 


GO 
CREATE NONCLUSTERED INDEX [IX_CountryID] 
    ON [dbo].[Companies]([CountryID] ASC); 

の任意のアイデアと、ここで間違って何ですか?

+0

その後、model.ApplicationUser_Company値がUserManager.CreateAsync前に正しいのですか? – DanielVorph

答えて

0

最後の提案のおかげでエラーが発生したようです。私は私のために働いていたコード...外部キーの代わりかのIDの値を設定する

をしようとしていた。

[HttpPost] 
public async Task<ActionResult> Register(RegisterViewModel model) 
{ 
    // verify the models' valid 
    if (ModelState.IsValid) 
    { 
     var user = new ApplicationUser { 
     /* ... */, 
     CompanyID = model.CompanyID // entity we retrieved 
     }; 

     // 
     // SignInManager yatta yata 
     // 
    } 
    return View(model); // Uh-oh fallback. 
} 
0

腸が、それは(分かりやすく/解説のための分割)このラインの中だ私に言っている:

var user = new ApplicationUser 
{ 
    UserName = model.Email, 
    Email = model.Email, 
    ApplicationUser_FirstName = model.ApplicationUser_FirstName, 
    ApplicationUser_LastName = model.ApplicationUser_LastName, 
    ApplicationUser_Company = model.ApplicationUser_Company  // <-- 
}; 

基本的には、フォームのアクション間の実体参照を渡すときに、全体の実体がないそうであるように、あなたは(IDを参照したいですセキュリティ上の目的(不正な入力、ハッキングなど)のためのものではありません。

あなたのViewModelに(この場合はRegisterViewModelは本当に唯一CompanyエンティティのPKでCompanyIDを()が必要です。そして、その後、userへの割り当てをルックアップを実行して、新しいユーザーApplicationUseruser)を投入するために使用されるべきであること。しかし例えば

[HttpPost] 
public async Task<ActionResult> Register(RegisterViewModel model) 
{ 
    // verify the models' valid 
    if (ModelState.IsValid) 
    { 
    // Perform a lookup to retrieve the selected company 
    var company = db.COmpanies.SingleOrDefault(x => x.CompanyID == model.CompanyID); 
    if (company != null) // Found it 
    { 
     // No go on to establish an application user 
     var user = new ApplicationUser { 
     /* ... */, 
     ApplicationUser_Company = company // entity we retrieved 
     }; 

     // 
     // SignInManager yatta yata 
     // 
    } 
    } 
    return View(model); // Uh-oh fallback. 
} 

注意、あなたのApplicationUserエンティティは二つの特性(ほとんどがそう)、ID用と外国人の関係のための1つを持っている場合、例えば

public int CompanyID { get; set; } // ID property 
[ForeignKey("CompanyID")] 
public virtual Company Company { get; set; } // entity property 

/またはを割り当てることができます。この場合、ApplicationUserを入力する前にルックアップを行う必要はなく、単に設定することができますuser.CompanyID = model.CompanyID;

+0

ありがとうブラッド!私はルックアップ 'var company = db.Companies ....'を追加しました。そして、私たちは謎を解くことに一歩近づいているようです。しかし、私はエラー "エンティティオブジェクトは、IEntityChangeTrackerの複数のインスタンスによって参照することはできません。"なにか提案を?そしてそれは初心者の質問の場合はごめんなさい... :) – Rok

関連する問題