我正在从MVC中的回发进行实体更新:
ControlChartPeriod period = _controlChartPeriodService.Get(request.PeriodId);
if (period != null)
{
SerializableStringDictionary dict = new SerializableStringDictionary();
dict.Add("lambda", request.Lambda.ToString());
dict.Add("h", request.h.ToString());
dict.Add("k", request.k.ToString());
period.Parameters = dict.ToXmlString();
// ToDo : fails on save every now and then when one of the values changes; fails on Foreign Key being null
try
{
_controlChartPeriodService.Update(period, request.PeriodId);
return Ok(request);
}
更新方法如下所示:
public TObject Update(TObject updated, TKey key)
{
if (updated == null)
return null;
TObject existing = _context.Set<TObject>().Find(key);
if (existing != null)
{
_context.Entry(existing).CurrentValues.SetValues(updated);
_context.SaveChanges();
}
return existing;
}
public TObject Get(TKey id)
{
return _context.Set<TObject>().Find(id);
}
奇怪的是,我第一次运行它通常效果很好;如果我第二次发回它不起作用,并且由于外键的EntityValidation错误而失败;但是,检查实体时,外键看起来很好并且未被使用。
我是否需要以某种方式同步上下文?
我一直在尝试寻找何时成功或何时不成功的差异。
我正在使用注入(inject)的存储库:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped((_) => new DataContext(ConfigSettings.Database.ConnectionString));
services.AddScoped<ControlChartPeriodService, ControlChartPeriodService>();
}
- 更新:
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public virtual ICollection<ControlChartPoint> ControlChartPoints { get; set; }
[Required]
public virtual ControlChart ControlChart { get; set; }
public string Parameters { get; set; }
在ControlChartMap中,我们具有以下内容:
HasMany(x => x.Periods)
.WithRequired(c => c.ControlChart);
最佳答案
如果您期望TObject的加载也包含该关系,那么在我看来,您的问题出在这一行:
TObject existing = _context.Set<TObject>().Find(key);
Find将仅加载TObject记录,而不加载其关系,并且由于代码中没有对ControlChart属性的显式引用,因此它不会延迟加载-这似乎是您期望的行为,所以我m假设您启用了延迟加载
关系已被配置为的事实
HasMany(x => x.Periods).WithRequired(c => c.ControlChart);
指示TObject的ControlChart属性是一组相关的Periods,但这并不意味着它在加载TObject时将强制延迟加载关系。
(我个人试图避免由于这种情况而导致对延迟加载的依赖,而是更喜欢实际上将其禁用,并希望通过使用Load来通过Include或以较小的方式通过一种显式load来积极地加载关系。关于个人品味的问题,但我发现这种方法可以使您免于很多头痛)
因此,如果启用了延迟加载并且喜欢它的工作方式,请在加载之间和保存之前的任何时间引用ControlChart属性,例如
var chart= existing.ControlChart;
或类似的东西
或用于非延迟加载方案,尽管它可以在任何情况下使用:
TObject existing = _context.Set<TObject>().Where(x=>x.Id==key).Include(x=> x.ControlChart).FirstOrDefault();