So I have the following Entities :
[Table("UserTbl")]
public abstract class User
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
[Required]
public string Username { get; set; }
[Required]
public DateTime CreatedDate { get; set; }
[Required]
public virtual UserPassword Password { get; set; }
[Required]
public string RegistrationNr { get; set; }
[Required]
public string ContactPerson { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string PhoneNr { get; set; }
[Required]
public bool HasBeenApproved { get; set; }
public DateTime? InactivationDate { get; set; }
}
[Table("UserPasswordTbl")]
public class UserPassword
{
[Required]
[Key]
[ForeignKey("User")]
public int UserId { get; set; }
[Required]
public User User { get; set; }
[Required]
public string Password { get; set; }
[Required]
public string Salt { get; set; }
public DateTime? PasswordChangedDate { get; set; }
public DateTime? LastPasswordFailureDate { get; set; }
public int PasswordFailuresSinceLastSuccess { get; set; }
}
Just a User object which has a property of a password object which is required for it to work.
then when the following method is called:
public string ActivateUser(string encryptedUsername)
{
string decryptedUsername = CryptographyTools.DecryptText(encryptedUsername);
User user = _userRepository.GetUser(decryptedUsername);
if (user != null)
{
user.HasBeenApproved = true;
_userRepository.SaveChanges();
}
return decryptedUsername;
}
a DbEntityValidationException is thrown. The EntityValidationErrors property of the exception suggests that the users Password property is not valid. However(!!), if I put a breakpoint somewhere after retrieving the user object from the repository and before the call to SaveChanges, this exception is not thrown and the entity is successfully updated in the database.
I had to fix this bug by removing the Required attribute from the Password property of the user entity.
I think EF is failing to load my object properly before a call is made to SaveChanges, maybe there is some weird yield return implementation.
//Siavash
Comments: Thanks, Yes, that is actually what I did, I expanded the watch window and made sure that the password property is not null. That probably caused it to load the property. I changed the method to: public string ActivateUser(string encryptedUsername) { string decryptedUsername = CryptographyTools.DecryptText(encryptedUsername); User user = _userRepository.GetUser(decryptedUsername); if (user != null) { user.HasBeenApproved = true; var load = user.Password; // Just to properly load the property _userRepository.SaveChanges(); } return decryptedUsername; } .. and tested that it works. This way, I get to keep my Required attribute on the property.
[Table("UserTbl")]
public abstract class User
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
[Required]
public string Username { get; set; }
[Required]
public DateTime CreatedDate { get; set; }
[Required]
public virtual UserPassword Password { get; set; }
[Required]
public string RegistrationNr { get; set; }
[Required]
public string ContactPerson { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string PhoneNr { get; set; }
[Required]
public bool HasBeenApproved { get; set; }
public DateTime? InactivationDate { get; set; }
}
[Table("UserPasswordTbl")]
public class UserPassword
{
[Required]
[Key]
[ForeignKey("User")]
public int UserId { get; set; }
[Required]
public User User { get; set; }
[Required]
public string Password { get; set; }
[Required]
public string Salt { get; set; }
public DateTime? PasswordChangedDate { get; set; }
public DateTime? LastPasswordFailureDate { get; set; }
public int PasswordFailuresSinceLastSuccess { get; set; }
}
Just a User object which has a property of a password object which is required for it to work.
then when the following method is called:
public string ActivateUser(string encryptedUsername)
{
string decryptedUsername = CryptographyTools.DecryptText(encryptedUsername);
User user = _userRepository.GetUser(decryptedUsername);
if (user != null)
{
user.HasBeenApproved = true;
_userRepository.SaveChanges();
}
return decryptedUsername;
}
a DbEntityValidationException is thrown. The EntityValidationErrors property of the exception suggests that the users Password property is not valid. However(!!), if I put a breakpoint somewhere after retrieving the user object from the repository and before the call to SaveChanges, this exception is not thrown and the entity is successfully updated in the database.
I had to fix this bug by removing the Required attribute from the Password property of the user entity.
I think EF is failing to load my object properly before a call is made to SaveChanges, maybe there is some weird yield return implementation.
//Siavash
Comments: Thanks, Yes, that is actually what I did, I expanded the watch window and made sure that the password property is not null. That probably caused it to load the property. I changed the method to: public string ActivateUser(string encryptedUsername) { string decryptedUsername = CryptographyTools.DecryptText(encryptedUsername); User user = _userRepository.GetUser(decryptedUsername); if (user != null) { user.HasBeenApproved = true; var load = user.Password; // Just to properly load the property _userRepository.SaveChanges(); } return decryptedUsername; } .. and tested that it works. This way, I get to keep my Required attribute on the property.