具有子集合验证错误的实体框架更新对象

时间:2018-03-04 01:34:24

标签: c# .net entity-framework

我使用EF 6.2.0。我有以下实体结构

FacilityGroup

public class FacilityGroup
{
    public int Id { get; set; }

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

    public string InternalNotes { get; set; }

    public virtual List<FacilityInstance> Facilities { get; set; } = new List<FacilityInstance>();
}

FacilityInstance

public class FacilityInstance
{
    public int Id { get; set; }

    [Required]
    [Index("IX_FacilityName")]
    [StringLength(450)]
    public string Name { get; set; }

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

    [Required]
    public virtual FacilityGroup FacilityGroup { get; set; }

    [ForeignKey(nameof(FacilityGroup))]
    [Index("IX_FacilityGroupId")]
    public int FacilityGroupId { get; set; }
}

正在调用的更新方法

public virtual async Task<OperationStatus> UpdateAsync(T obj, bool requireSave = true)
{
    var operationStatus = new OperationStatus { Status = true };

    try
    {
        DataContext.Entry(obj).State = EntityState.Modified;
    }

    catch (Exception exp)
    {
        operationStatus = OperationStatus.CreateFromException("Error updating " + typeof(T) + ".", exp);
        //throw;
    }

    if (operationStatus.Status && requireSave)
    {
        operationStatus = await SaveAsync();
    }

    return operationStatus;
}

SaveAsync

public virtual async Task<OperationStatus> SaveAsync()
{
    var operationStatus = new OperationStatus { Status = true };

    try
    {
        var res = await DataContext.SaveChangesAsync();
        operationStatus.RecordsAffected = res;
        operationStatus.Status = operationStatus.RecordsAffected > 0;
    }
    catch (Exception exp)
    {
        operationStatus = OperationStatus.CreateFromException("Could not save object.", exp);
        //throw;
    }

    return operationStatus;
}

OperationStatus

[DebuggerDisplay("Status: {" + nameof(Status) + "}")]
public class OperationStatus
{
    public bool Status { get; set; }
    public int RecordsAffected { get; set; }
    public string Message { get; set; }
    public object OperationId { get; set; }
    public string ExceptionMessage { get; set; }
    public string ExceptionStackTrace { get; set; }
    public string ExceptionInnerMessage { get; set; }
    public string ExceptionInnerStackTrace { get; set; }

    public static OperationStatus CreateFromException(string message, Exception ex)
    {
        var status = new OperationStatus
        {
            Status = false,
            Message = message,
            OperationId = null
        };

        if (ex != null)
        {
            status.ExceptionMessage = ex.Message;
            status.ExceptionStackTrace = ex.StackTrace;
            status.ExceptionInnerMessage = ex.InnerException?.Message;
            status.ExceptionInnerStackTrace = ex.InnerException?.StackTrace;
        }

        return status;
    }
}

问题是当我为一个现有 FacilityGroup调用UpdateAsync时,从上下文中提取而不更改FacilityGroup.Facilities集合(根据调试正确加载) )我收到集合中每个项目的验证错误,表明需要FacilityGroup。我试图更改FacilityGroup.Name

2 个答案:

答案 0 :(得分:0)

此:

[Required]
public virtual FacilityGroup FacilityGroup { get; set; }

完全错了。 FacilityGroup是一个导航属性,除了[ForeignKey]之外,它不应该有任何属性。您将[Required]应用于存储在数据库中的属性,在本例中为FacilityGroupId。 但是,由于FacilityGroupIdint(不能是null),因此不需要[Required]属性。

另外,假设你正确地遵循约定优于配置,你应该删除[ForeignKey]并最终得到:

public virtual FacilityGroup FacilityGroup { get; set; }

[Index("IX_FacilityGroupId")]
public int FacilityGroupId { get; set; }

通常,导航属性放在类的底部,在所有属性之后。

答案 1 :(得分:0)

我发现了这个问题,原因是AutoMapper。我的收藏集如下:

.ForMember(x => x.Facilities, opt => opt.UseDestinationValue());

将其更改为:

.ForMember(x => x.Facilities, opt => opt.Ignore());

解决了这个问题