Entity Framework 6 AttachAsModified

Entity Framework 6 AttachAsModified

我正在尝试将 EF 从 4.x 更新到 6.x(通过 nuget 的最新稳定版)。经过一些工作后,该应用程序可用于数据检索但不能用于保存。
出于性能原因,我们主要使用 EF 4.x 中的 "AttachAsModified" 方法。大多数情况下我们有主键,附加,修改我们要更新的值,最后保存。
EF 6.x 没有这样的方法所以我尝试了以下方法:

var data = new CatalogNode
{
    CatalogNodeId = catalogNodeId,
    UpdatedOn = updatedOn,
    UpdatedBy = updatedBy,
 };

  CatalogNodes.Attach(data);
  var entry = Entry(data);
  entry.Property(e => e.UpdatedOn).IsModified = true;
  entry.Property(e => e.UpdatedBy).IsModified = true;

不幸的是,EF 抛出一个 "DbEntityValidationException",表示需要并设置一些额外的属性。

编辑:
这是生成的 CatalogNodes 实体(setter 包括对 OnPropertyChanged 的​​调用)

public partial class CatalogNode : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public CatalogNode()
    {
        this.CatalogArticles = new HashSet<CatalogArticle>();
        this.LocalizedCatalogNodes = new HashSet<LocalizedCatalogNode>();
        this.CatalogNodeAttributeValues = new HashSet<CatalogNodeAttributeValue>();
        this.CatalogNodeMappings = new HashSet<CatalogNodeMapping>();
        this.TranslatedCatalogNodeNames = new HashSet<TranslatedCatalogNodeName>();
        this.CatalogNodeMediaAssets = new HashSet<CatalogNodeMediaAsset>();
    }

    private System.Guid _catalognodeid;
    public System.Guid CatalogNodeId  {get;set;}

    private string _catalognodeuid;
    public string CatalogNodeUid  {get;set;}

    private System.Guid _catalogid;
    public System.Guid CatalogId  {get;set;}

    private int _catalognodetype;
    public int CatalogNodeType  {get;set;}

    private Nullable<System.Guid> _parentid;
    public Nullable<System.Guid> ParentId  {get;set;}

    private Nullable<System.Guid> _linkid;
    public Nullable<System.Guid> LinkId  {get;set;}

    private int _sequence;
    public int Sequence  {get;set;}

    private Nullable<System.Guid> _attributegroupid;
    public Nullable<System.Guid> AttributeGroupId  {get;set;}

    private string _printcatalogtemplateuid;
    public string PrintCatalogTemplateUid  {get;set;}

    private bool _printcatalogpagebreak;
    public bool PrintCatalogPageBreak  {get;set;}

    private System.DateTime _createdon;
    public System.DateTime CreatedOn  {get;set;}

    private string _createdby;
    public string CreatedBy  {get;set;}

    private System.DateTime _updatedon;
    public System.DateTime UpdatedOn  {get;set;}

    private string _updatedby;
    public string UpdatedBy {get;set;}


    public virtual AttributeGroup AttributeGroup { get; set; }
    public virtual Catalog Catalog { get; set; }
    public virtual ICollection<CatalogArticle> CatalogArticles { get; set; }
    public virtual ICollection<LocalizedCatalogNode> LocalizedCatalogNodes { get; set; }
    public virtual ICollection<CatalogNodeAttributeValue> CatalogNodeAttributeValues { get; set; }
    public virtual CatalogNode LinkedCatalogNode { get; set; }
    public virtual ICollection<CatalogNodeMapping> CatalogNodeMappings { get; set; }
    public virtual ICollection<TranslatedCatalogNodeName> TranslatedCatalogNodeNames { get; set; }
    public virtual ICollection<CatalogNodeMediaAsset> CatalogNodeMediaAssets { get; set; }

    public void OnPropertyChanged(string propertyName)
    {
        if(PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

我收到的错误信息如下:
- "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details."
- "The field \"CreatedBy\" 是必需的。"

第一个问题:我在哪里可以看到或设置哪些字段是必填的?我们目前使用数据库优先方法。
第二个问题:有解决方法吗?生成的更新查询不会更新那些额外的属性。当然,我可以将这些附加属性设置为一些随机值并将这些属性标记为未更改,但我希望必须有更好的方法。

感谢您的帮助!

1) 我在哪里可以查看或设置哪些字段是必需的?

它们在 edmx 文件中被标记为不可为空:

或标有[必填]属性:

[Required]
public string Name { get; set;} 

或者用 Fluent 标记为 IsRequired() 调用 API:

modelBuilder.Entity<Person>().Property(t => t.Name).IsRequired();

或者他们现在允许设置空值:

public int Age { get; set; }

例如,这允许空值:

public int? Age { get; set; }

2) 有解决方法吗?

对于部分更新,我知道的唯一解决方法是在未修改的属性上设置一些垃圾值,只是为了通过验证。例如,让我们更新 id = 1 的人的年龄 属性:

var person = new Person();
person.Id = 1;
person.Name = ""; // not null string to pass validation
person.Age = 25;

var entry = context.Entry(person);
entry.Property(e => e.Age).IsModified = true;
context.SaveChanges();

重要提示:不需要 Attach()。

我发现验证不适用于部分更新。一种解决方案是覆盖 ValidateEntity 方法或通过将 ValidateOnSaveEnabled 属性设置为 false 来禁用验证。两者都位于数据库配置 class.