实体框架:当我执行EntityState.Modified时发生了参照完整性约束违规

时间:2015-06-13 17:01:06

标签: asp.net entity-framework referential-integrity

我在ASP.NET MVC 4中创建了一个网站。 它已经很久了,我有这个错误:发生了参照完整性约束违规。 我尝试更新数据库中的条目时。当有人想购买产品时,我需要更换购买的用户。

我有两个一对多的关系。

修改 这是我的用户类:

public class User
{
    private string email, password, firstname, lastname;
    private Adress shippingAdress, billingAdress;
    private bool isConnected;
    private List<Product> products;
    //private List<Auction> auctions;
    private long idShippingA, idBillingA;

    public User()
    {
        products = new List<Product>();
    }

   /* public List<Auction> Auctions
    {
        get { return auctions; }
        set { auctions = value; }
    }

    public void AddAuction(Auction auction)
    {
        if (auction != null)
            auctions.Add(auction);
    }*/

    public long IdBillingA
    {
        get { return idBillingA; }
        set
        {
            if (value < 0)
                throw new ArgumentException("The id of the billing adress should not be negative");
            idBillingA = value;
        }
    }

    public long IdShippingA
    {
        get { return idShippingA; }
        set
        {
            if (value < 0)
                throw new ArgumentException("The id of the shipping adress should not be negative");
            idShippingA = value;
        }
    }

    public bool IsConnected
    {
        get { return isConnected; }
        set { isConnected = value; }
    }

    public virtual List<Product> Products
    {
        get { return products; }
        set
        {
            if (value == null)
                throw new ArgumentNullException("The list of product should not be null");
            products = value;
        }
    }

    public Adress BillingAdress
    {
        get { return billingAdress; }
        set
        {
            if (value == null)
                throw new ArgumentNullException("The billing adress should not be null");
            billingAdress = value;
        }
    }

    public Adress ShippingAdress
    {
        get { return shippingAdress; }
        set
        {
            if (value == null)
                throw new ArgumentNullException("The shipping adress should not be null");
            shippingAdress = value;
        }
    }

    public string Password
    {
        get { return password; }
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("The password should not be null or empty");
            password = value;
        }
    }

    public string Email
    {
        get { return email; }
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("The email should not be null or empty");
            email = value;
        }
    }

    public string Lastname
    {
        get { return lastname; }
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("The lastname should not be null or empty");
            lastname = value;
        }
    }

    public string Firstname
    {
        get { return firstname; }
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("The fistname should not be null or empty");
            firstname = value;
        }
    }
}
    }

修改 这是我的产品类:

public class Product
{
    private long id, strategyId;
    private User userWhoSell;
        private User userWhoBuy;
    private string userWhoSellId, userWhoBuyId, name, description, urlPicture, isBought;

    public string IsBought
    {
        get { return isBought; }
        set { isBought = value; }
    }
    private SellStrategy strategy;
    private float price;
    private string strategyString;
    public Product()
    {
        isBought = "F";
    }

    public float Price
    {
        get { return price; }
        set 
        {
            if (value < 0)
                throw new ArgumentException("The price should not be negative");
            price = value; 
        }
    }

    public string StrategyString
    {
        get { return strategyString; }
        set 
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("The strategy string should not be null, empty or with white space");
            strategyString = value; 
        }
    }

    public long StrategyId
    {
        get { return strategyId; }
        set 
        {
            if (value < 0)
                throw new ArgumentException("The strategy id should not be negative");
            strategyId = value; 
        }
    }

    public SellStrategy Strategy
    {
        get { return strategy; }
        set 
        {
            if (value == null)
                throw new ArgumentNullException("The strategy should not be null");
            strategy = value; 
        }
    }

    public string SellerId
    {
        get { return userWhoSellId; }
        set 
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("The user id should not be null, empty or with white space");
            userWhoSellId = value; 
        }
    }

    public string BuyerId
    {
        get { return userWhoBuyId; }
        set 
        {
            userWhoBuyId = value; 
        }
    }

    public string UrlPicture
    {
        get { return urlPicture; }
        set 
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("The picture's url should not be null, empty or with white space");
            urlPicture = value; 
        }
    }

    public long Id
    {
        get { return id; }
        set 
        {
            if (value < 0)
                throw new ArgumentException("The id should not be negative");
            id = value;
        }
    }

    public string Description
    {
        get { return description; }
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("The description should not be null, empty or with white space");
            description = value;
        }
    }

    public string Name
    {
        get { return name; }
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("The name should not be null, empty or with white space");
            name = value;
        }
    }

    public virtual User Buyer
    {
        get { return userWhoBuy; }
        set
        {
            userWhoBuy = value;
        }
    }

    public virtual User Seller
    {
        get { return userWhoSell; }
        set 
        {
            if (value == null)
                throw new ArgumentNullException("The user should not be null");
            userWhoSell = value; 
        }
    }
}

修改 这是我的背景:

public class Context : DbContext
{
    public Context(string connString)
        : base(connString) { }

    public DbSet<User> Users { get; set; }
    public DbSet<Adress> Adress { get; set; }
    public DbSet<Product> Products { get; set; }

    //public DbSet<Auction> Auctions { get; set; }

    public DbSet<SellStrategy> Strategies { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<User>().HasKey<string>(u => u.Email);
        modelBuilder.Entity<Adress>().HasKey<long>(a => a.Id);
        modelBuilder.Entity<Product>().HasKey<long>(p => p.Id);
        modelBuilder.Entity<Auction>().HasKey<long>(au => au.Id);

        modelBuilder.Entity<Product>()
     .HasRequired(p => p.Seller)
     .WithMany(u => u.Products)
     .HasForeignKey(p => p.SellerId)
     .WillCascadeOnDelete(false);
        // Otherwise you might get a "cascade causes cycles" error

        modelBuilder.Entity<Product>()
           .HasOptional(p => p.Buyer)
           .WithMany() // No reverse navigation property
           .HasForeignKey(p => p.BuyerId)
           .WillCascadeOnDelete(false);

       // modelBuilder.Entity<Auction>().HasMany<User>(au => au.Users).WithMany(u => u.Auctions);
       // modelBuilder.Entity<Auction>().HasRequired(au => au.Product).WithMany().WillCascadeOnDelete(false);

        modelBuilder.Entity<User>().HasRequired(u => u.BillingAdress).WithMany().HasForeignKey(u => u.IdBillingA).WillCascadeOnDelete(false);
        modelBuilder.Entity<User>().HasRequired(u => u.ShippingAdress).WithMany().HasForeignKey(u => u.IdShippingA).WillCascadeOnDelete(false);
        modelBuilder.Entity<User>().Ignore(u => u.IsConnected);



        modelBuilder.Entity<Product>().HasRequired<SellStrategy>(p => p.Strategy).WithMany().WillCascadeOnDelete(false);
        modelBuilder.Entity<Product>().Ignore(p => p.StrategyString);
        modelBuilder.Entity<Product>().Ignore(p => p.Price);

        modelBuilder.Entity<SellStrategy>().Property(s => s.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        modelBuilder.Entity<AuctionSelling>().HasKey<long>(a => a.Id);
        modelBuilder.Entity<AuctionSelling>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("AuctionSelling");
        });
        modelBuilder.Entity<DirectSelling>().HasKey<long>(d => d.Id);
        modelBuilder.Entity<DirectSelling>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("DirectSelling");
        });
        modelBuilder.Entity<SellStrategy>().Property(s => s.SoldDate).IsOptional();
    }
}

修改 当我尝试更新我的产品时:

public void UpDateProduct(Product product)
    {
        using(Context context = new Context(connectionString))
        {
            try
            {
                Product p = GetById(product.Id);
                //context.Products.Attach(p);
                p.BuyerId = product.BuyerId;
                p.Buyer = product.Buyer;
                p.IsBought = "T";

                context.Entry(p).State = EntityState.Modified;
                context.SaveChanges();
            }
            catch (Exception ex)
            {
            }
        }
    }

这是

  

context.Entry(p).State = EntityState.Modified;

引发错误。

这是完整的错误

  

发生了参照完整性约束违规:&#39; User.Email&#39;的属性值。在一段关系的一端与&#39; Product.BuyerId&#39;的属性值不匹配。在另一端。

当我执行context.saveChanges时,什么也没发生......  我不知道该怎么做......我想哭... ^^ ... 非常感谢你提前了!

1 个答案:

答案 0 :(得分:1)

这是由在构造函数中设置引用导航属性引起的。具体做法是:

userWhoSell = new User();
userWhoBuy = new User();

这意味着Product开始有两个虚拟User对象,您必须替换才能使它们变得有意义。否则EF可能会尝试保存这些虚拟对象。我很确定通过......

context.Entry(p).Entity.Buyer = product.Buyer;

...您实际设置了一个空的User对象,其键值为no email,而不是您之前设置的键值Product.BuyerId

我会说:在实体的构造函数中删除大多数这些初始化。初始化集合是有道理的。有时设置默认值(但不是主键值),但引用导航属性永远不会。另见:EF codefirst : Should I initialize navigation properties?

旁注:我也不会使用属性设置器进行验证。这就是数据注释的用途。尝试从数据库中实现实体时,这些异常可能会干扰EF。