Entity Framework:当我执行 EntityState.Modified 时发生参照完整性约束冲突
Entity Framework : A referential integrity constraint violation occurred when I do EntityState.Modified
我在 ASP.NET MVC 4 中创建了一个网站。
我有这个错误已经很久了:发生参照完整性约束冲突。
这是当我试图更新我的数据库中的条目时。那么当有人想购买产品时,我需要更改购买的用户。
我有两个一对多的关系。
编辑
这是我的用户 class :
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;
}
}
}
}
编辑
这是我的产品 Class :
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;
引发错误。
这是完整的错误
A referential integrity constraint violation occurred: The property value(s) of 'User.Email' on one end of a relationship do not match the property value(s) of 'Product.BuyerId' on the other end.
当我只做 context.saveChanges 时,什么也没有发生...
我不知道该怎么办...我想哭^^...
非常感谢您!
这是由于在构造函数中设置引用导航属性引起的。具体来说:
userWhoSell = new User();
userWhoBuy = new User();
这意味着 Product
开始有两个虚拟 User
对象,您 必须替换 才能使它们变得有意义。否则 EF 可能会尝试保存这些虚拟对象。我很确定...
context.Entry(p).Entity.Buyer = product.Buyer;
...你实际上设置了这样一个空的User
对象,它有一个键值no email
,而不是你之前显然设置的键值Product.BuyerId
。
我会说:删除实体构造函数中的大部分初始化。初始化集合很有意义。有时设置默认值(但不是主键值),但引用导航属性 never。另见:EF codefirst : Should I initialize navigation properties?
旁注:我也不会使用 属性 setter 进行验证。这就是数据注释的用途。尝试从数据库中具体化实体时,这些异常可能会干扰 EF。
我在 ASP.NET MVC 4 中创建了一个网站。 我有这个错误已经很久了:发生参照完整性约束冲突。 这是当我试图更新我的数据库中的条目时。那么当有人想购买产品时,我需要更改购买的用户。
我有两个一对多的关系。
编辑 这是我的用户 class :
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;
}
}
}
}
编辑 这是我的产品 Class :
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;
引发错误。
这是完整的错误
A referential integrity constraint violation occurred: The property value(s) of 'User.Email' on one end of a relationship do not match the property value(s) of 'Product.BuyerId' on the other end.
当我只做 context.saveChanges 时,什么也没有发生... 我不知道该怎么办...我想哭^^... 非常感谢您!
这是由于在构造函数中设置引用导航属性引起的。具体来说:
userWhoSell = new User();
userWhoBuy = new User();
这意味着 Product
开始有两个虚拟 User
对象,您 必须替换 才能使它们变得有意义。否则 EF 可能会尝试保存这些虚拟对象。我很确定...
context.Entry(p).Entity.Buyer = product.Buyer;
...你实际上设置了这样一个空的User
对象,它有一个键值no email
,而不是你之前显然设置的键值Product.BuyerId
。
我会说:删除实体构造函数中的大部分初始化。初始化集合很有意义。有时设置默认值(但不是主键值),但引用导航属性 never。另见:EF codefirst : Should I initialize navigation properties?
旁注:我也不会使用 属性 setter 进行验证。这就是数据注释的用途。尝试从数据库中具体化实体时,这些异常可能会干扰 EF。