c# - .Include() EF Coe 的更新问题
问题描述
我一直在关注 有关在 EF 核心中处理并发冲突的ms 文档教程。我有两个模型:
电影.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;
}
}
流派.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
。我发现导致问题的错误是对Include d in的Genre.GenreTitle
属性进行验证。即使ModelState没有失败,它仍然会导致更新实体的错误。但是,当我检查Movie.Genre属性时完全没问题,应该没有任何错误。只有当我从中删除.Include时才有效。movie
var movieToUpdate = await _context.Movie.FirstOrDefaultAsync(id)
现在,我想知道我的错误是什么,因为在文档中嵌套对象实际上是.Include d。
解决方案
我测试了你的正则表达式^[A-Z]+[a-zA-Z]*$
,它似乎不接受空格字符。所以Genre Title
不匹配表达式并触发错误。
您可以在 中添加空格[]
来告诉表达式您还需要接受空格字符。我不知道它是否应该如何完成,但它适用于RegexStorm或Regex101(最后一个没有 c#,但我认为 Regex 有点通用)。
推荐阅读
- database - 计算 B+ 树内存使用量(最小值、最大值)
- javascript - 打字稿命名空间参考不起作用
- scala - 如何在 apache zeppelin 0.8.2 上使用带有 Scala 2.12 的 spark 将 spark 3.x 提交给 yarn?
- java - 为什么在尝试清除 Canvas 时出现错误(Nullpointerexception)?
- vue-component - 在单独的 Vue 组件中单击按钮加载另一个 Vue 组件
- r - R lme4模型:计算连续预测器的最大值-最小值之间的效果大小
- python - 将带有参数的方法标记为测试并在 unittest 上提供内联参数
- reactjs - 访问已在其他组件中使用 react 查询获取的数据
- amazon-web-services - S3 HTTPS 对象 URL 无法通过 vpc 端点访问
- python - dash_bootstrap_components 'form' 的'Action' 属性