c# - ASP.NET db.savechange System.Data.Entity.Infrastruct.DbUpdateException

标签 c# asp.net .net entity-framework concurrency

所以,我遇到了一个奇怪的情况,

我收到此错误消息:

System.Data.Entity.Infrastructure.DbUpdateException: 'An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.'

InnerException:

OptimisticConcurrencyException: Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions.

我正在尝试使用 AJAX 和 .NET 构建一款纸牌游戏,

现在,问题是我有一个 Method1 ,需要在 Room 实体中进行一些更改,这是该方法的完整代码:

   public string OpenCards()
    {
        IsLogged = (System.Web.HttpContext.Current.User != null) && System.Web.HttpContext.Current.User.Identity.IsAuthenticated;
        if (IsLogged)
            CurrentUser = db.Users.Find(User.Identity.GetUserId());
        else
            return "NotLoggedIn";

        if (CurrentUser.CurrentRoom == null)
            return "UserNotConnectedToRoom";

        if (CurrentUser.CurrentRoom.Round == 0)
        {
            CurrentUser.CurrentRoom.SetAllPlayingThisRound(true);

            // DELETE THE PREVIOUS CurrentUser.CurrentRoom.CardsDeck
            CurrentUser.CurrentRoom.RemovePlayersCards(db); 
            if(CurrentUser.CurrentRoom.CardsDeck != null) 
            {
                db.Cards.RemoveRange(CurrentUser.CurrentRoom.CardsDeck);
            }

            List<Card> list = RoomManager.FillDeck(CurrentUser.CurrentRoom);
            CurrentUser.CurrentRoom.CardsDeck = list;

            CurrentUser.CurrentRoom.SendCardsToPlayers();
            db.SaveChanges(); // ERROR HAPPENS HERE


            return "....";


        }

        return "";
    }

我在执行以下操作时收到消息错误:db.SaveChanges()

所以基本上,从这段代码中重要的是要知道我正在更改三个实体:ApplicationUser、Room 和 Cards。

现在,每隔几秒就会调用Method2,它所做的基本上就是显示数据库上下文中的一些数据。

根据我在互联网上阅读的内容,出现此错误的原因有两个:

  1. 正如错误本身所说:与 Null 相关的内容。
  2. 与并发相关的内容。

现在奇怪的是,这个错误并不是一直发生,而且我无法重现它,也不知道它发生的原因。

因此,在尝试修复它之前,我如何知道此错误的原因是 1. 还是 2.?在 Debug模式下我应该寻找什么?

编辑:

我的模型:

public class Card
{
    public int CardId { get; set; }
    public int Value { get; set; }
    public string Type { get; set; }
}

public class Room
{
    public int RoomId { get; set; }
    public string Name { get; set; }
    public int EnterPrice { get; set; }
    public int UserDecisionTime { get; set; }
    public virtual ICollection<Card> CardsDeck { get; set; }
    public virtual ICollection<Card> CardsOnTable { get; set; }
    public int WhosTurnChairIndex { get; set; }
    public virtual ApplicationUser Chair0 { get; set; }
    public virtual ApplicationUser Chair1 { get; set; }
    public virtual ApplicationUser Chair2 { get; set; }
    public virtual ApplicationUser Chair3 { get; set; }
    public virtual ApplicationUser Chair4 { get; set; }
    public int FirstRound { get; set; }
    public int Round { get; set; }
}

以及来自 SQL Server 的一些卡片数据:

enter image description here

enter image description here

编辑:在 @Train 建议在更改数据库的每一行之后进行 db.SaveChanges() 后,我注意到在此行之后收到错误:

CurrentUser.CurrentRoom.SendCardsToPlayers();

这就是方法:

    public void SendCardsToPlayers()
    {
        for (int i = 0; i < 5; i++)
        {
            ApplicationUser user = (ApplicationUser)GetProperty(this, "Chair" + i);

            if (user != null && user.IsPlayingThisRound == true && IsPlayerHasEnoughMoney(user))
            {
                Card c1 = CardsDeck.First();
                CardsDeck.Remove(c1);

                Card c2 = CardsDeck.First();
                CardsDeck.Remove(c2);

                user.CardOne = c1;
                user.CardTwo = c2;
            }
            else if (user != null)
            {
                user.IsPlayingThisRound = false;
            }
        }
    } 

此方法放置在 Room 的实体中。

另一个注意:我尝试删除以下行:CardsDeck.Remove(c1); 和 CardsDeck.Remove(c2);

但是还是报这个错误。

所以问题在于:Card c1 = CardsDeck.First();

也许因为我不是从 CardsDeck.ToList() 制作的,所以会出现问题?

编辑:根据请求,FillDeck的方法:

    public static List<Card> FillDeck(Room room)
    {
        List<Card> list = new List<Card>();
        string[] names = new string[]
        {
            "Club", "Diamond", "Heart", "Spade"
        };

        // Creating the Card deck

        for(int i = 0; i < 13; i++)
        {
            for(int j = 0; j < 4; j++)
            {
                list.Add(new Card
                {
                    Value = i,
                    Type = names[j]
                });
            }
        }

        list.Shuffle();
        return list;
    }

**另一个注意事项:**我发现如果我删除与卡片相关的所有内容,它们是:

  • RoomManager.FillDeck(CurrentUser.CurrentRoom);
  • CurrentUser.CurrentRoom.SendCardsToPlayers(db);
  • db.Cards.RemoveRange(CurrentUser.CurrentRoom.CardsDeck.ToList());

它工作没有问题,问题是否可能是由于卡实体引起的? 我想到的另一个解决方案是将 Card 作为字符串(用逗号分隔)甚至字符串中的 JSON,这样它可能会解决整个 Cards 问题?

最佳答案

很难判断缺少某些方法的代码发生了什么。这就是我认为的问题所在。

您的实体具有以下属性

{
     CardID: ... //Primary Key
     value: ...
     Type: ...
     CurrentRoom... //is this a foreign Key?
     ...//other properties
}

但是当您创建它时,您只有 2 个属性。

           list.Add(new Card
            {
                Value = i,
                Type = names[j] 
            }); //no foriegn key or primary key defined

您无法对不完整的实体执行数据库操作。您还没有为卡定义Primaryforeign键,然后当您执行所有数据库操作时,它不知道要对哪些卡执行增删改查操作。

关于c# - ASP.NET db.savechange System.Data.Entity.Infrastruct.DbUpdateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57733174/

相关文章:

c# - 无法选择数据绑定(bind)的 DataGridView 中的复选框

javascript - asp.net 中的 ValidationExpression 验证数字和字符(/和 -)

asp.net - 如何在 ASP.NET 页面上注册自定义服务器控件

.net - ServiceRoute + WebServiceHostFactory 杀死 WSDL 生成?如何使用 ?wsdl 创建无扩展 WCF 服务

c# - 用于 OneCode C# 实现的 Twilio Authy 2FA

c# - 使用 HttpServer 测试 ASP.NET WebAPI 中的 ConfigurationManager

c# - Powershell 导入自定义 C# CMDlet,无可用 "ExportedCommands"

c# - 尝试保存 Emitted 程序集时抛出 NotSupportedException

c# - SelectMany 压平嵌套结构

c# - 如何在 MVC View 中更改显示格式