【问题标题】:EF SaveChanges method throws: The relationship could not be changed because one or more of the foreign-key properties is non-nullableEF SaveChanges 方法抛出:无法更改关系,因为一个或多个外键属性不可为空
【发布时间】:2013-08-09 12:13:48
【问题描述】:

当我从我的 winforms 应用程序保存订单时,它可以正常工作。但是当我尝试添加第二个时,SaveChanges() 方法会引发异常:

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

我有一个表“Orders”和一个具有外键 OrderID 的“Orderlines”。

有人知道为什么会这样吗?

我知道我的上下文处理并不理想,所以如果这是问题所在,任何关于如何改变它的建议都将非常有用!

public class Orders
{
    private readonly DataContext _context;

    public Orders()
    {
        _context = EntityContext.Context;
    }

    public int Save(Order order)
    {
        if (order.ID > 0)
            _context.Entry(order).State = EntityState.Modified;
        else
        {
            _context.Orders.Add(order);
        } 
            _context.SaveChanges();
            return order.ID;
    }
}
public class EntityContext : IDisposable
{
    private static DataContext _context;
    public static DataContext Context
    {
        get
        {
            if (_context != null)
                return _context;
            return _context = new DataContext();
        }
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }
}

EDIT 1添加了Order类和异常时间的订单截屏

我已将更新完整性设置为 CASCADE。

Orderlines 是一个关系表。

public partial class Order
{
    public Order()
    {
        this.Orderlines = new HashSet<Orderline>();
    }

    public int ID { get; set; }
    public System.DateTime CreatedDate { get; set; }
    public int PaymentType { get; set; }
    public Nullable<int> SettlementID { get; set; }
    public Nullable<decimal> CashPayment { get; set; }
    public Nullable<decimal> BankPayment { get; set; }
    public Nullable<int> UserID { get; set; }

    public virtual ICollection<Orderline> Orderlines { get; set; }
    public virtual Settlement Settlement { get; set; }
}

EDIT 2 - 部分类

我有扩展 order 和 orderline 对象的部分类:

public partial class Order 
{
    public decimal Total
    {
        get { return Orderlines.Sum(x => x.Quantity*x.Price); }
    }
    public decimal TotalExMva
    {
        get { return Orderlines.Sum(x => (x.Quantity*x.Price)/(x.Vat + 1)); }
    }
    public decimal Mva
    {
        get { return Total - TotalExMva; }
    }

}

public partial class Orderline
{
    public decimal Total
    {
        get { return (Price*Quantity); }         
    }

    public string ProductName
    {

        get
        {
            var currentProductId = ProductID;
            return new Products().Get(currentProductId).Name;
        }
    }
}

EDIT 3 - 订单和产品类别

public partial class Orderline
{
    public int ID { get; set; }
    public int ProductID { get; set; }
    public int Quantity { get; set; }
    public decimal Price { get; set; }
    public decimal Vat { get; set; }
    public int OrderID { get; set; }

    public virtual Order Order { get; set; }
    public virtual Product Product { get; set; }
}
public partial class Product
{
    public Product()
    {
        this.Orderlines = new HashSet<Orderline>();
    }

    public int ID { get; set; }
    public string Name { get; set; }
    public string GTIN { get; set; }
    public decimal Price { get; set; }
    public decimal Vat { get; set; }

    public virtual ICollection<Orderline> Orderlines { get; set; }
}

【问题讨论】:

  • 如果(在 sql 中)标记为 ReferentialIntegrity 的 NavigationProperty 没有值,通常会发生这种情况您的订单对象是什么样的?
  • @Grumbler85 我用一些额外的数据编辑了我的帖子。至于引用完整性,我会阅读。
  • 我会检查 SettlementID 和/或 UserID - 是否允许空值?关系到?
  • SettlementID 和 UserID 是 forreignkeys 并且允许设置为空。
  • orderline 对象(我看到 count=1)呢?这个 orderline 对象是否引用了显示的 order 对象?

标签: c# entity-framework-4


【解决方案1】:

【讨论】:

  • 请注意,不鼓励link-only answers,因此答案应该是搜索解决方案的终点(与另一个参考文献的中途停留相比,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,并保留链接作为参考。
猜你喜欢
  • 1970-01-01
  • 2015-12-16
  • 2013-10-19
  • 2014-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多