一个或多个外键属性是不可为空的EF6

时间:2017-12-28 14:44:25

标签: c# entity-framework

我一直试图看一下我创建的一个方法中的缺陷,即更新(包括添加)一个对象,以及它是使用Entity Framework 6.0的子代。我已经查看了所有其他SO问题,但我无法看到我的错误。我有一个产品实体,可以有一个孩子的列表,这些孩子可以有一个孩子的列表。

这是我的产品实体

public partial class Product
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Product()
    {
        ProductSizes = new HashSet<ProductSize>();
    }

    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Name { get; set; }

    public int? PortfolioId { get; set; }

    public bool IsActive { get; set; }

    public int CreatedBy { get; set; }

    public DateTime? CreatedDate { get; set; }

    public int UpdatedBy { get; set; }

    public DateTime? UpdatedDate { get; set; }

    // This is a lookup entity that contains 1:1 relationship
    public virtual Portfolio Portfolio { get; set; }

    // This is a lookup entity that contains 1:1 relationship
    public virtual User CreatedByUser { get; set; }

    // This is a lookup entity that contains 1:1 relationship
    public virtual User UpdatedByUser{ get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<ProductSize> ProductSizes { get; set; }
}

产品可以有很多孩子的ProductSize

public partial class ProductSize
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public ProductSize()
    {
        ProductPackages = new HashSet<ProductPackage>();
    }

    public int Id { get; set; }

    [ForeignKey("Product")]
    public int ProductId { get; set; }

    public int? CanSizeId { get; set; }

    [StringLength(50)]
    public string CanUPC { get; set; }

    public int CreatedBy { get; set; }

    public DateTime? CreatedDate { get; set; }

    public int UpdatedBy { get; set; }

    public DateTime? UpdatedDate { get; set; }

    public bool IsActive { get; set; }

    // This is a lookup entity that contains 1:1 relationship
    public virtual CanSize CanSize { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<ProductPackage> ProductPackages { get; set; }

    // Parent Product
    public virtual Product Product { get; set; } 

    // This is a lookup entity that contains 1:1 relationship
    public virtual User CreatedByUser{ get; set; }

    // This is a lookup entity that contains 1:1 relationship
    public virtual User UpdatedByUser{ get; set; }
}

ProductSize可以有很多ProductPackage

public partial class ProductPackage
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public ProductPackage()
    {          
    }

    public int Id { get; set; }

    [ForeignKey("ProductSize")]
    public int ProductSizeId { get; set; }

    public int PackageSizeId { get; set; }

    [StringLength(50)]
    public string CarrierCode { get; set; }

    public int? SAPId { get; set; }

    [StringLength(50)]
    public string CaseUPCSupplierPack { get; set; }

    public int CreatedBy { get; set; }

    public DateTime? CreatedDate { get; set; }

    public int UpdatedBy { get; set; }

    public DateTime? UpdatedDate { get; set; }

    public bool IsActive { get; set; }

    // This is a lookup entity that contains 1:1 relationship
    public virtual PackageSize PackageSize { get; set; }

    // This is a lookup entity that contains 1:1 relationship
    public virtual User CreatedByUser{ get; set; }

    // Parent ProductSize
    public virtual ProductSize ProductSize { get; set; }

    // This is a lookup entity that contains 1:1 relationship
    public virtual User UpdatedByUser{ get; set; }
}

我有一个接受产品并更新它的方法,并且如果需要,还可以在链中添加任何实体。

public void UpdateProduct(Product product, int userId)
{
    var originalProduct = GetAllProductEntities().Where(a => a.Id == product.Id).SingleOrDefault();

    var prouctEntry = _dbContext.Entry(originalProduct);
    prouctEntry.CurrentValues.SetValues(newProduct);

    foreach (var size in newProduct.ProductSizes)
    {
        var originalSize = originalProduct.ProductSizes.Where(a => a.Id == size.Id).SingleOrDefault();

        if (originalSize != null)
        {

            var sizeEntry = _dbContext.Entry(originalSize);
            sizeEntry.CurrentValues.SetValues(size);
        }
        else
        {
            // No -> It's a new child item -> Insert
            size.Id = 0;
            originalProduct.ProductSizes.Add(size);
        }
        foreach (var package in size.ProductPackages)
        {
            var originalPackage = originalSize.ProductPackages.Where(a => a.Id == package.Id).SingleOrDefault();

            if (originalPackage != null)
            {

                var packageEntry = _dbContext.Entry(originalPackage);
                packageEntry.CurrentValues.SetValues(package);
            }
            else
            {
                // No -> It's a new child item -> Insert
                package.Id = 0;
                originalSize.ProductPackages.Add(package);
            }
        }
    }
    _dbContext.SaveChanges();
}

调用SaveChanges()之后,我得到了这个System.InvalidOperationException

  

'操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。'

如上所述,我已经阅读了大部分有关此问题的SO /问题,我相信这是我的模型的一个问题,但我很遗憾它可能是什么。此模型是从现有数据库生成的,因此如果我的模式出现问题,我也可以更改它。如果需要,我还可以提供更多代码片段。

0 个答案:

没有答案