Reputation: 1207
So, I got a weird situation,
I get this error message:
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.
I'm trying to build a card-game using AJAX and .NET,
Now, the thing is I have a Method1 that requires to make some changes in a Room entity, this is the full code of the method:
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 "";
}
I get the message error while doing: db.SaveChanges()
So basically, from this code what matters to know is that I'm changing three entities: ApplicationUser, Room and Cards.
Now, every few seconds, Method2 is being called, and what it does is basically displaying some data from the db context.
Now from what I've read on the internet, this error occur from two reasons:
Now the weird thing is, this error doesn't happen all the time, and I can't reproduce it, nor knowing the reason why it happens.
So before trying to fix it, how would I know whether the reason for this error is 1. or 2.? what should I looking for in the debugging mode?
Edit:
My Models:
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; }
}
And some Data of cards from the SQL Server:
Edit: After @Train 's suggestion to make db.SaveChanges() after every line of changing the database, I noticed that I receive an error after this line:
CurrentUser.CurrentRoom.SendCardsToPlayers();
So this is the method:
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;
}
}
}
This method is placed in Room's entity.
ANOTHER NOTE: I tried to remove the lines: CardsDeck.Remove(c1); and CardsDeck.Remove(c2);
but it's still make this error.
So the problem is at: Card c1 = CardsDeck.First();
maybe because I don't make from CardsDeck.ToList(), it makes problems?
Edit: As request, FillDeck's method:
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;
}
** Another Note: ** I found out that if I delete everything related to Cards, which are:
it works with no problem, is the problem might be caused because of Card entity? Another solution I thought about is to make Card as a string ( split with commas ) or even JSON inside the string, so it might solve the whole Cards issue?
Upvotes: 2
Views: 872
Reputation: 1207
So I managed to solve the problem, instead of using Card, I just used a string property and made a split using comma, a full example can be found here:
Entity Framework - Code First - Can't Store List<String>
Tho, it means that I really had an issue with Card, since it could be owned by many Entities: Room, ApplicationUser it probably caused some issues with null foreign key.
Upvotes: 1
Reputation: 3496
It's kind of hard to tell what's going on with the code you have some methods missing. Here is what I think the problem is.
Your Card
Entity has the properties
{
CardID: ... //Primary Key
value: ...
Type: ...
CurrentRoom... //is this a foreign Key?
...//other properties
}
But when you create it you only have 2 properties.
list.Add(new Card
{
Value = i,
Type = names[j]
}); //no foriegn key or primary key defined
You can't do DB operations with an incomplete entity. You haven't defined the Primary
and foreign
keys for the cards and then when you do all your db operations, it doesn't know which cards to do the crud operations on.
Upvotes: 1