【发布时间】:2021-07-04 19:01:37
【问题描述】:
我一直在关注ms docs tutorial 处理 EF 核心中的并发冲突。我有两个模型:
Movie.cs
public class Movie
{
[Key]
public int ID { get; set; }
[Required]
[StringLength(60, MinimumLength = 3)]
public string Title { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Release Date")]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }
[Range(1, 300)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18,2)")]
public decimal Price { get; set; }
[Required]
[StringLength(5)]
[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
public string Rating { get; set; }
public string Description { get; set; }
[Timestamp]
public byte[] ConcurrencyToken { get; set; }
public int GenreId { get; set; }
public Genre Genre { get; set; }
public override string ToString()
{
return Title;
}
}
Genre.cs
public class Genre
{
public Genre()
{
Movies = new List<Movie>();
}
[Key]
public int GenreId { get; set; }
[Required]
[StringLength(30, MinimumLength = 5)]
[Display(Name = "Genre Title")]
[RegularExpression(@"^[A-Z]+[a-zA-Z]*$")]
public string GenreTitle { get; set; }
[Timestamp]
public byte[] ConcurrencyToken { get; set; }
[Display(Name = "Number of movies")]
public ICollection<Movie> Movies { get; set; }
public override string ToString()
{
return GenreTitle;
}
}
当我尝试更新我的模型时,我遇到了一些奇怪的问题,但不知道为什么,没有抛出任何错误,模型只是没有得到更新。这是我的post 更新方法:
public async Task<IActionResult> OnPostAsync(int? id)
{
if (!ModelState.IsValid)
{
return Page();
}
// ConcurrencyToken may have changed.
var movieToUpdate = await _context.Movie
.Include(m => m.Genre)
.FirstOrDefaultAsync(m => m.ID == id);
if(movieToUpdate == null)
{
return HandleDeletedMovie();
}
// Set ConcurrencyToken to value read in OnGetAsync
_context.Entry(movieToUpdate).Property(
m => m.ConcurrencyToken).OriginalValue = Movie.ConcurrencyToken;
if (await TryUpdateModelAsync<Movie>(
movieToUpdate,
"movie",
m => m.Title, m => m.ReleaseDate,
m => m.Price, m => m.Rating,
m => m.GenreId))
{
try
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch(DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
var clientValues = (Movie)exceptionEntry.Entity;
var databaseEntry = exceptionEntry.GetDatabaseValues();
if(databaseEntry == null)
{
ModelState.AddModelError(string.Empty, "Unable to save. The movie was deleted by another user.");
return Page();
}
var dbValues = (Movie)databaseEntry.ToObject();
await SetDbErrorMessage(dbValues, clientValues, _context);
// Save the current ConcurrencyToken so next postback
// matches unless an new concurrency issue happens.
Movie.ConcurrencyToken = (byte[])dbValues.ConcurrencyToken;
// Clear model error for the next postback
ModelState.Remove($"{nameof(Movie)}.{nameof(Movie.ConcurrencyToken)}");
}
}
// Get errors from TryUpdate
var validationErrors = ModelState.Values.Where(E => E.Errors.Count > 0)
.SelectMany(E => E.Errors)
.Select(E => E.ErrorMessage)
.ToList();
PopelateGenresDropDownList(_context, movieToUpdate.Genre);
return Page();
}
更新在TryUpdateModelAsync 线上失败,并且没有转到try-catch。我发现导致问题的错误是对Genre.GenreTitle 属性的验证,该属性是movie 中的Included。即使 ModelState 没有失败,它仍然会导致更新实体的错误。但是,当我检查 Movie.Genre 属性时完全没问题,应该没有任何错误。只有当我从 var movieToUpdate = await _context.Movie.FirstOrDefaultAsync(id) 中删除 .Include 时,它才成功。
现在,我想知道我的错误是什么,因为在文档中嵌套对象实际上是 .Included.
【问题讨论】:
标签: c# entity-framework-core razor-pages