EF Code First ApplicationUser 需要 DateTime 未添加
EF Code First ApplicationUser required DateTime not added
我在使用新 ASP.NET 核心应用程序(代码优先)注册新用户时遇到问题。
注册时,我使用的是继承自 IdentityUser 的 ApplicationUser。
public class ApplicationUser : IdentityUser
{
[Required]
[DefaultValue(5)]
public int ViewerRange { get; set; }
[DefaultValue(false)]
[Required]
public bool IsTACAccepted { get; set; }
public DateTime? TACAccepted { get; set; }
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime Created { get; set; }
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime Modified { get; set; }
public string Role { get; set; }
public ApplicationUser()
{
Modified = DateTime.Now;
Created = DateTime.Now;
}
}
这是Register.cshtml.cs
的部分
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
if (ModelState.IsValid)
{
var user = new ApplicationUser
{
UserName = Input.Email,
Email = Input.Email,
Role = Input.Role,
Created = DateTime.Now,
Modified = DateTime.Now,
IsTACAccepted = false,
ViewerRange = 5
};
var result = await _userManager.CreateAsync(user, Input.Password);
//[...]
注册时,CreateAsync 方法失败并出现以下错误:
InvalidOperationException: The value for property 'ApplicationUser.Modified' cannot be set to null because its type is 'System.DateTime' which is not a nullable type.
我不明白为什么会失败。
有人可以详细解释一下吗?
亲切的问候
public DateTime? Created { get; set; }
public DateTime? Modified { get; set; }
使用这个,你的模型需要被告知你的数据库中可以有空值,否则它会假设没有。
更新
**I did not actually carefully noticed your error. Now I will update my answer:-**
我看到你没有在你的控制器中使用这个 属性。所以最初这个 属性 可以为空。为此,您发现了这个问题。首先,使用此 属性 忽略可空值。
这样试试:-
public DateTime TACAccepted { get; set; } = DateTime.Now;
您可以试试这个,因为您的 属性 它是空的。您可以像上面的代码一样设置此 属性 以忽略可为空的。或者,如果不需要,您可以从模型中删除此 属性。我认为它会解决您的问题。
此外,请确保该列在您的 SQL 数据库中声明为 DateTime。
错误的原因是[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
说它的值是由数据库生成的,所以任何分配的值都应该被忽略。错误显示情况并非如此。
这不是代码中唯一的奇怪之处。 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
在 DateTime 上没有意义。 IDENTITY 用于自动递增数字字段。这对 DateTime 列没有意义。
如果您想自己指定值,请删除 DatabaseGenerated 属性并将它们用作普通字段。您可以通过指定默认 属性 值来避免显式赋值,例如
public DateTime Created { get; set; } = DateTime.Now;
public DateTime Modified { get; set; } = DateTime.Now;
也可以配置 数据库 来生成这些值。这在文档的 Generated Values article. Adding Created
and Modified
columns is described in the Date/time generation 部分中进行了描述。
Created
列的默认值约束可以用 HasDefaultValueSql
指定:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.Created)
.HasDefaultValueSql("getdate()");
}
Modified
时间戳需要一个触发器,它不能在 DbContext 的模型中指定。这必须在数据库中直接创建:
CREATE TRIGGER [dbo].[Blogs_UPDATE] ON [dbo].[Blogs]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;
DECLARE @Id INT
SELECT @Id = INSERTED.BlogId
FROM INSERTED
UPDATE dbo.Blogs
SET LastUpdated = GETDATE()
WHERE BlogId = @Id
END
或者通过执行相同脚本的原始 SQL 迁移:
migrationBuilder.Sql(
@"
EXEC ('CREATE TRIGGER [dbo].[Blogs_UPDATE] ON [dbo].[Blogs]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;
DECLARE @Id INT
SELECT @Id = INSERTED.BlogId
FROM INSERTED
UPDATE dbo.Blogs
SET LastUpdated = GETDATE()
WHERE BlogId = @Id
END')");
我在使用新 ASP.NET 核心应用程序(代码优先)注册新用户时遇到问题。
注册时,我使用的是继承自 IdentityUser 的 ApplicationUser。
public class ApplicationUser : IdentityUser
{
[Required]
[DefaultValue(5)]
public int ViewerRange { get; set; }
[DefaultValue(false)]
[Required]
public bool IsTACAccepted { get; set; }
public DateTime? TACAccepted { get; set; }
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime Created { get; set; }
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime Modified { get; set; }
public string Role { get; set; }
public ApplicationUser()
{
Modified = DateTime.Now;
Created = DateTime.Now;
}
}
这是Register.cshtml.cs
的部分public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
if (ModelState.IsValid)
{
var user = new ApplicationUser
{
UserName = Input.Email,
Email = Input.Email,
Role = Input.Role,
Created = DateTime.Now,
Modified = DateTime.Now,
IsTACAccepted = false,
ViewerRange = 5
};
var result = await _userManager.CreateAsync(user, Input.Password);
//[...]
注册时,CreateAsync 方法失败并出现以下错误:
InvalidOperationException: The value for property 'ApplicationUser.Modified' cannot be set to null because its type is 'System.DateTime' which is not a nullable type.
我不明白为什么会失败。
有人可以详细解释一下吗?
亲切的问候
public DateTime? Created { get; set; }
public DateTime? Modified { get; set; }
使用这个,你的模型需要被告知你的数据库中可以有空值,否则它会假设没有。
更新
**I did not actually carefully noticed your error. Now I will update my answer:-**
我看到你没有在你的控制器中使用这个 属性。所以最初这个 属性 可以为空。为此,您发现了这个问题。首先,使用此 属性 忽略可空值。
这样试试:-
public DateTime TACAccepted { get; set; } = DateTime.Now;
您可以试试这个,因为您的 属性 它是空的。您可以像上面的代码一样设置此 属性 以忽略可为空的。或者,如果不需要,您可以从模型中删除此 属性。我认为它会解决您的问题。
此外,请确保该列在您的 SQL 数据库中声明为 DateTime。
错误的原因是[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
说它的值是由数据库生成的,所以任何分配的值都应该被忽略。错误显示情况并非如此。
这不是代码中唯一的奇怪之处。 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
在 DateTime 上没有意义。 IDENTITY 用于自动递增数字字段。这对 DateTime 列没有意义。
如果您想自己指定值,请删除 DatabaseGenerated 属性并将它们用作普通字段。您可以通过指定默认 属性 值来避免显式赋值,例如
public DateTime Created { get; set; } = DateTime.Now;
public DateTime Modified { get; set; } = DateTime.Now;
也可以配置 数据库 来生成这些值。这在文档的 Generated Values article. Adding Created
and Modified
columns is described in the Date/time generation 部分中进行了描述。
Created
列的默认值约束可以用 HasDefaultValueSql
指定:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.Created)
.HasDefaultValueSql("getdate()");
}
Modified
时间戳需要一个触发器,它不能在 DbContext 的模型中指定。这必须在数据库中直接创建:
CREATE TRIGGER [dbo].[Blogs_UPDATE] ON [dbo].[Blogs]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;
DECLARE @Id INT
SELECT @Id = INSERTED.BlogId
FROM INSERTED
UPDATE dbo.Blogs
SET LastUpdated = GETDATE()
WHERE BlogId = @Id
END
或者通过执行相同脚本的原始 SQL 迁移:
migrationBuilder.Sql(
@"
EXEC ('CREATE TRIGGER [dbo].[Blogs_UPDATE] ON [dbo].[Blogs]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;
DECLARE @Id INT
SELECT @Id = INSERTED.BlogId
FROM INSERTED
UPDATE dbo.Blogs
SET LastUpdated = GETDATE()
WHERE BlogId = @Id
END')");