EF6 虚拟对象不再可用



我有一个新的问题,我不知道它是怎么出现的。

public static int SaveNewProjectGraphic(string svgString, int pageId, ApplicationDbContext db, string user = "System")
{
db = new ApplicationDbContext();   //tried with new and with db-context given from controller-action
LayoutGraphic layoutGraphic = new LayoutGraphic()
{
byUser = user,
EditorSettingId = pageId,
SvgString = svgString
};
db.LayoutGraphics.Add(layoutGraphic);
db.SaveChanges();
layoutGraphic.EditorSetting.Project.LastChange = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
layoutGraphic.EditorSetting.Project.byUser = user;
db.Entry(layoutGraphic.EditorSetting.Project).State = EntityState.Modified;
string newId = layoutGraphic.Id.ToString();
string newSvgString = svgString.Replace("newGraphicId", "g" + newId);
layoutGraphic.SvgString = newSvgString;
db.Entry(layoutGraphic).State = EntityState.Modified;
db.SaveChanges();
return layoutGraphic.Id;
}

在上面的静态函数中,我创建了一个新记录。
在数据库之后。SaveChanges(( 我通常得到与新记录关联的虚拟记录(编辑器设置(。
现在,我可以使用此关联来更改该记录的某些属性(字段(。

我 100% 确定这以前有效,但不知何故它被破坏了(不仅在这个模型上(,所以我只在 EditorSet 上得到一个空引用异常(当然还有与 Editorset 相关的项目(。
我不知道,我做了什么:-(

这里是LayouGraphic模型(详细信息(:

public class LayoutGraphic : BaseEntity
{
[Display(Name = "SVG")]
public string SvgString { get; set; }
public int EditorSettingId { get; set; }
public virtual EditorSetting EditorSetting{ get; set; }
}

以及关联的主模型:

public class EditorSetting
{
//defaults setzen
public EditorSetting()
{
ViewBox = "0 0 600 500";
Created = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
LastChange = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
}
public int Id { get; set; }
public int ProjectId { get; set; }
public virtual Project Project { get; set; }
public string ViewBox { get; set; }
public string ViewName { get; set; }
public string Pagenumber { get; set; }
public string Created { get; set; }
public string LastChange { get; set; }
public string byUser { get; set; }
//1:n Beziehung zu Unterfunktionen
public virtual ICollection<SubFunction> SubFunctions { get; set; }
}

有什么想法吗? 谢谢卡斯滕

这种行为差异是长期存在的 DbContext 的结果。 通过在方法中声明新的 DbContext,您将永远不会看到通过在实体上设置 EditorSettingId FK 并保存它来更新的编辑器设置引用。

当您使用生存期较长的 DbContext 时,您可能会看到它已更新,前提是 DBContext 知道它。(引用的编辑器设置是 DbContext 中的跟踪实体(

例如:

假设我们有一个父实体和子实体。父级包含子项的集合,子项包含父级 ID FK 和虚拟父级导航属性。父 ID#1 存在于数据库中:

using (var context = new TestDbContext())
{
var newChild = new Child { Name = "Freddy", BirthDate = new DateTime(1999, 3, 3), ParentId = 1 };
context.Children.Add(newChild);
context.SaveChanges();
}

现在在SaveChanges之后的这一点上,如果你看一下newChild的Parent参考,就会 #null。 相反,如果您这样做:

using (var context = new TestDbContext())
{
var neverUsedParent = context.Parents.Single(x => x.ParentId == 1);
var newChild = new Child { Name = "Freddy", BirthDate = new DateTime(1999, 3, 3), ParentId = 1 };
context.Children.Add(newChild);
context.SaveChanges();
}

在此示例中,保存更改后,您将看到 Parent 引用存在,即使我们没有关联它,我们仍然只设置 ID。

当您有一个长期存在的 DbContext 时,设置 FK 属性时的行为必然会发生差异,并且它可能会产生在运行时显示的非常奇怪的后果。 如果其中一个 EditorSettings 之前已由该 DbContext 从数据库加载,则使用该 EditorSettingId 创建新记录将填充关联,而另一个 EditorSettingId 则不会。 (因为 DbContext 不知道它( 在此调用之前,如果使用相同的 DbContext 实例,则该 EditorSet 可能已加载到代码中的任何位置。

即使这样做:

using (var context = new TestDbContext())
{
var newChild = new Child { Name = "Freddy", BirthDate = new DateTime(1999, 3, 3), ParentId = 1 };
context.Children.Add(newChild);
context.SaveChanges();
// newChild.Parent == #null here....
var neverUsedParent = context.Parents.Single(x => x.ParentId == 1);
// newChild.Parent is available here!
}

通常,最好避免同时映射导航属性和 FK。我建议实体应该使用其中之一。使用导航属性时,可以使用 EF Core 中的影子属性或 EF 6 中的Map.MapKey()映射没有属性的 FK。对于我想加载/操作大量数据并且不需要相关详细信息的情况,我将在这些实体中使用没有导航属性的 FK。

我想到了为什么会发生这种情况:

  1. 上下文中从延迟加载更改为预先加载(请参阅此处(,因此在 首先保存更改,访问用于从数据库加载它的编辑器设置属性。
  2. 数据库中已存在具有该特定 ID 的 EditoSetting 对象。如果在方法中创建新上下文,则这无关紧要。但是你提到它使用了 在控制器中,所以也许流中的东西是 改变。

相关内容

最新更新