我的回应是方法2
概要
我想只修改实体的几列以及添加\修改嵌套的子实体
- 在这里,我正在更新
Scenario 实体并仅修改ScenarioDate。
- 在其子实体中,即导航属性
TempScenario,我正在添加一条新记录
- 在嵌套的子实体
Scenariostation 中,我还添加了修改记录
public partial class Scenario
{
public Scenario()
{
InverseTempscenario = new HashSet<Scenario>();
Scenariostation = new HashSet<Scenariostation>();
}
public int Scenarioid { get; set; }
public string Scenarioname { get; set; }
public DateTime? Scenariodate { get; set; }
public int Streetlayerid { get; set; }
public string Scenarionotes { get; set; }
public int? Modifiedbyuserid { get; set; }
public DateTime? Modifieddate { get; set; }
public int? Tempscenarioid { get; set; }
public virtual Scenario Tempscenario { get; set; }
public virtual ICollection<Scenario> InverseTempscenario { get; set; }
public virtual ICollection<Scenariostation> Scenariostation { get; set; }
}
public partial class Scenariostation
{
public Scenariostation()
{
Scenariounit = new HashSet<Scenariounit>();
}
public int Scenariostationid { get; set; }
public int Scenarioid { get; set; }
public int Stationid { get; set; }
public bool? Isapplicable { get; set; }
public int? Createdbyuserid { get; set; }
public int? Modifiedbyuserid { get; set; }
public DateTime? Modifieddate { get; set; }
public virtual Scenario Scenario { get; set; }
public virtual Station Station { get; set; }
}
public partial class Station
{
public Station()
{
Scenariostation = new HashSet<Scenariostation>();
}
public int Stationid { get; set; }
public string Stationname { get; set; }
public string Address { get; set; }
public NpgsqlPoint? Stationlocation { get; set; }
public int? Modifiedbyuserid { get; set; }
public DateTime? Modifieddate { get; set; }
public virtual ICollection<Scenariostation> Scenariostation { get; set; }
}
-
使用 EF Core,如果您不想进行 2 次数据库往返,那么在断开连接的情况下更新数据会很棘手。
-
尽管 2 次数据库访问似乎并不重要,但如果数据表有数百万条记录,它可能会影响性能。
-
另外,如果只有少数列需要更新,包括嵌套子实体的列,Usual Approach 将不起作用
通常的做法
public virtual void Update(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
var returnEntity = _dbSet.Attach(entity);
_context.Entry(entity).State = EntityState.Modified;
}
但是这里的问题是断开连接的 EF Core 更新,如果你使用这个DbContext.Entry(entity).EntityState = EntityState.IsModified,所有的列都会更新。
因此某些列将更新为其默认值,即 null 或默认数据类型值。
此外,ScenarioStation 的某些记录根本不会更新,因为实体状态将为 UnChanged。
因此,为了仅更新从客户端发送的列,需要以某种方式告知 EF Core。
使用 ChangeTracker.TrackGraph
最近我发现了这个DbConetxt.ChangeTracker.TrackGraph方法,可以用来标记实体的Added,UnChanged状态。
不同之处在于,使用TrackGraph,您可以添加自定义逻辑,因为它迭代地导航实体的导航属性。
我使用 TrackGraph 的自定义逻辑
public virtual void UpdateThroughGraph(T entity, Dictionary<string, List<string>> columnsToBeUpdated)
{
if (entity == null)
throw new ArgumentNullException("entity");
_context.ChangeTracker.TrackGraph(entity, e =>
{
string navigationPropertyName = e.Entry.Entity.GetType().Name;
if (e.Entry.IsKeySet)
{
e.Entry.State = EntityState.Unchanged;
e.Entry.Property("Modifieddate").CurrentValue = DateTime.Now;
if (columnsToBeUpdated.ContainsKey(navigationPropertyName))
{
foreach (var property in e.Entry.Properties)
{
if (columnsToBeUpdated[e.Entry.Entity.GetType().Name].Contains(property.Metadata.Name))
{
property.IsModified = true;
}
}
}
}
else
{
e.Entry.State = EntityState.Added;
}
});
}
通过这种方法,我可以轻松地处理任何嵌套子实体及其列的所需列更新以及新的添加/修改。