【问题标题】:What Causes The INSERT statement conflicted with the FOREIGN KEY constraint?什么原因导致 INSERT 语句与 FOREIGN KEY 约束冲突?
【发布时间】:2013-03-13 03:10:26
【问题描述】:

这段代码以前对我有用,但我不确定是什么导致了这个错误。我唯一的猜测是,当我尝试创建玩家时,团队数据被发送回团队表并尝试复制,但由于 TeamId 是唯一的,因此出现此错误。

错误

INSERT 语句与 FOREIGN KEY 约束“FK_dbo.Players_dbo.Teams_TeamId”冲突。冲突发生在数据库“Web”、表“dbo.Teams”、列“TeamId”中。声明已终止。

播放器

public class Player
{
    ...
    ...

    [HiddenInput(DisplayValue = false)]
    [ForeignKey("Team")]
    public int TeamId { get; set; }        

    public virtual Team Team { get; set; }

    ...
}

团队

public class Team
{
    [Key]
    [HiddenInput(DisplayValue = false)]
    public int TeamId { get; set; }

    ....

    public virtual ICollection<Player> Players { get; set; }
}

控制器

//
    // GET: /Player/
    [HttpGet]
    public ActionResult Create()
    {
        PopulateTeamsDropDownList();
        return View();
    }

    //
    // POST: /Player/
    [HttpPost]
    public ActionResult Create(Player model)
    {
        if (ModelState.IsValid)
        {
            using (var db = new EfDb())
            {
                var userProfile = db.UserProfiles.Single(u => u.UserName == User.Identity.Name);
                if (userProfile != null)
                {
                    var player = new Player
                                     {
                                         UserProfile = userProfile,                                             
                                         ....
                                         ....                                              
                                     };                        
                    db.Players.Add(player);                          

                    db.SaveChanges();
                }
            }
        }
        PopulateTeamsDropDownList(model.TeamId);
        return View(model);
    }

    private void PopulateTeamsDropDownList(object selectedTeams = null)
    {
        var teamsQuery = from d in _iService.Teams
                         orderby d.Name
                         select d;
        ViewBag.TeamID = new SelectList(teamsQuery, "TeamId", "Name", selectedTeams);
    }

查看

<div class="editor-label">
            @Html.LabelFor(model => model.TeamId, "Pick Your Team")
    </div>
    <div class="editor-field">
        @Html.DropDownList("TeamId", String.Empty)
        @Html.ValidationMessageFor(model => model.TeamId)
    </div>

如何解决这个错误?

【问题讨论】:

    标签: c# asp.net-mvc-4 visual-studio-2012 ef-code-first entity-framework-ctp5


    【解决方案1】:

    您应该尝试为您的玩家实体完成团队等实体。尤其是外键。

    [HttpPost]
        public ActionResult Create(Player model)
        {
            if (ModelState.IsValid)
            {
                using (var db = new EfDb())
                {
                    //Since you have the username cached, you can check the local EF cache for the object before hitting the db.
                    //var userProfile = db.UserProfiles.Single(u => u.UserName == User.Identity.Name);
                    var userProfile = db.UserProfiles.Local.SingleOrDefault(u => u.UserName == User.Identity.Name) 
                                   ?? db.UserProfiles.SingleOrDefault(u => u.UserName == User.Identity.Name);
                    if (userProfile != null)
                    {
                        var player = new Player
                                         {
                                             UserProfile = userProfile,                                             
                                             ....
                                             ....                                              
                                         };  
                        player.TeamId = 5;                      
                        db.Players.Add(player);                          
    
                        db.SaveChanges();
                    }
                }
            }
            PopulateTeamsDropDownList(model.TeamId);
            return View(model);
        }
    

    并确保您视图中的 Dropdown 是必需的,并将正确的值发送到 post 方法。

    【讨论】:

    • 谢谢哥们,原来player.TeamId = 5; 是关键。我不知道我是怎么错过的。
    • @Floradu88 您正在对数据库进行不必要的访问,只是为了检查播放器是否存在。如果您检查代码中的 Id,您已经知道它存在。您应该更新它,因为它会导致不良的性能实践。
    • @FeistyMango 这是我的原始代码,我之所以去数据库,是因为PlayerUserProfile 的孩子,我需要UserIdPlayer
    • @KomengeMwandila 我看到了更新版本。但是,我肯定会添加一篇关于缓存 UserProfile 的文章,因为它会导致同样不必要的性能损失。
    • @KomengeMwandila 在这种情况下,EF 已经在缓存用户配置文件。您只需要跟踪 Id,然后您就可以从 EF 的本地缓存中检索它。
    【解决方案2】:

    这背后的原因是,当您在 child 表上插入一条记录时,parent 表上的引用列的值尚不存在。

    考虑以下场景:

    // PARENT TABLE
    CREATE TABLE TableA
    (
       ID INT PRIMARY KEY
    );
    
    // CHILD TABLE
    CREATE TABLE TableB
    (
       ID INT PRIMARY KEY,
       TableA_ID INT,
       CONSTRAINT tb_FK FOREIGN KEY (TableA_ID) REFERENCES TableA(ID)
    );
    
    
    // RECORDS OF PARENT TABLE
    INSERT INTO TableA (ID) VALUES (1);
    INSERT INTO TableA (ID) VALUES (2);
    
    // RECORDS OF CHILD TABLE
    INSERT INTO TableB (ID, TableA_ID) VALUES (1,1);
    INSERT INTO TableB (ID, TableA_ID) VALUES (2,1);
    INSERT INTO TableB (ID, TableA_ID) VALUES (3,2);
    

    如果你执行上面的语句,它不会失败,因为它们都没有违反参照完整性规则。

    尝试执行以下语句:

    INSERT INTO TableB (ID, TableA_ID) VALUES (3,4);
    

    它失败是因为4 是要插入的TableA_ID 的值在Table1.ID 上不存在。外键保留了记录之间的参照完整性。

    【讨论】:

    • 我相信这也可以,但是自从Code First之后,我很久没有执行普通的SQL了。
    • 尝试对特定任务使用种子方法:P
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-27
    • 2021-05-30
    相关资源
    最近更新 更多