I've extended IdentityUser
with a ApplicationUser
class with several custom fields to match the AspNetUsers
table I have in a SQL Server DB. A couple of them are defined in SQL as, for example: MyDate datetime2 null
. In my ApplicationUser
class it would be: datetime? MyDate;
.
Now, the only way I can set it to null is with a T-SQL command separate from Entity Framework and if it is null, my application throws an exception reading it from the DB.
I do admit that it was erroneously declared as datetime MyDate
in ApplicationUser
for awhile before I updated it to match the DB. Is this the cause of the problems I'm seeing? If so, how do I get my ApplicationUser
to match the current DB schema?
Here's the exception:
01/10/19 17:14:47.034 ERROR 114 MyApp.Global - Exception occurred:
System.Web.HttpUnhandledException (0x80004005): Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.Data.ConstraintException: The 'MyDateUtc' property on 'ApplicationUser' could not be set to a 'null' value. You must set this property to a non-null value of type 'System.DateTime'.
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper.ErrorHandlingValueReader`1.GetValue(DbDataReader reader, Int32 ordinal)
at lambda_method(Closure , Shaper )
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper.HandleEntityAppendOnly[TEntity](Func`2 constructEntityDelegate, EntityKey entityKey, EntitySet entitySet)
at lambda_method(Closure , Shaper )
at System.Data.Entity.Core.Common.Internal.Materialization.Coordinator`1.ReadNextElement(Shaper shaper)
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.SimpleEnumerator.<MoveNextAsync>d__4.MoveNext()
Here's the ApplicationUser
class (trimmed a bit) and supporting classes:
public class ApplicationUser : IdentityUser<long, CustomUserLogin, CustomUserRole, CustomUserClaim>
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.None)]
public override long Id
{
get { return base.Id; }
set { base.Id = value; }
}
public DateTime? MyDateUtc { get; set; }
public ClaimsIdentity GenerateUserIdentity(UserManager<ApplicationUser, long> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = manager.CreateIdentity(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)
{
return Task.FromResult(GenerateUserIdentity(manager));
}
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole, long, CustomUserLogin, CustomUserRole, CustomUserClaim>
{
public ApplicationDbContext() : base("MyDbConnection")
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
public class CustomUserRole : IdentityUserRole<long> { }
public class CustomUserClaim : IdentityUserClaim<long> { }
public class CustomUserLogin : IdentityUserLogin<long> { }
public class CustomRole : IdentityRole<long, CustomUserRole>
{
public CustomRole() { }
public CustomRole(string name) { Name = name; }
}
public class CustomUserStore : UserStore<ApplicationUser, CustomRole, long, CustomUserLogin, CustomUserRole, CustomUserClaim>
{
public CustomUserStore(ApplicationDbContext context) : base(context)
{
}
}
public class CustomRoleStore : RoleStore<CustomRole, long, CustomUserRole>
{
public CustomRoleStore(ApplicationDbContext context) : base(context)
{
}
}
DateTime is a Struct
and as such, is a value type. This means it the cannot be set to null
.
You may solve your problem with the help of the nullable operator. Using a question mark (?) after the type or using the generic style Nullable.
Nullable <DateTime> MyDateUtc;
or
DateTime? MyDateUtc;
You should check your DbContext
class just in case your class' property is being set as required. More info here
User contributions licensed under CC BY-SA 3.0