我有一个非常简单的类似拍卖的应用程序。使用EF 6。x和我得到吨奇怪的行为时,试图删除一个孩子(出价)从父母(上市)。我在应用程序的其他地方删除具有类似关系类型的实体,没有任何问题。涉及的实体:
public class Listing {
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ListingID { get; set; }
[Required]
public bool Active { get; set; }
[Required]
[StringLength(128)]
public string UserID { get; set; }
[ForeignKey("UserID")]
public ApplicationUser User { get; set; }
public List<Bid> Bids { get; set; }
public Listing() {
User = new ApplicationUser();
Bids = new List<Bid>();
}
}
public class Bid {
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int BidID { get; set; }
[Required]
public decimal Amount { get; set; }
[Required]
public DateTime Created { get; set; }
[Required]
[StringLength(128)]
public string UserID { get; set; }
public int ListingID { get; set; }
[ForeignKey("UserID")]
public ApplicationUser User { get; set; }
[ForeignKey("ListingID")]
public Listing Listing { get; set; }
public Bid() {
User = new ApplicationUser();
Listing = new Listing();
}
}
public class ApplicationUser : IdentityUser {
public List<Listing> Listings { get; set; }
public List<Bid> Bids { get; set; }
public ApplicationUser() {
Listings = new List<Listing>();
Bids = new List<Bid>();
}
}
在这个特定的上下文中,我按用户查询出出价并删除它们:
public bool RemoveBids(string offenderUserID) {
using (var db = new MyDbContext()) {
var bids = db.Bids
.Include(l => l.Listing)
.Where(x => x.UserID == offenderUserID && x.Listing.Active == true);
foreach (var bid in bids) {
bid.User = null;
bid.Listing = null;
db.Bids.Remove(bid);
db.Entry(bid).State = EntityState.Deleted;
}
return db.SaveChanges() == 1 ? true : false; //exception on SaveChanges()
}
}
直到我取消竞标。在清单中,我得到一个DbEntityValidationException,说清单的字段是必需的。在调试器中浏览它会发现EF试图将新的实体添加到bid中。用户和出价。疯了……但OK。我一直在做,最后得到了你上面看到的……这导致了另一个XXX
UserName字段是必需的。
UserName在IdentityUser (AspNetUsers表)中作为身份框架的一部分。
仍在尝试添加ApplicationUser…不知何故,某个地方吗?在我上面查询的图中没有任何地方存在ApplicationUser对象。我就是看不出来。
检查表显示字段与上面的实体完全相同。
这是我的第一个重要的Code-First项目。我曾经参与过一些相当大的DB-First项目,使用/edmx模型,从来没有遇到过这么多的障碍和奇怪的"陷阱"。大多数事情似乎都行得通。我应该转换这个东西吗?我在这么简单的事情上浪费了太多时间。我想喜欢EF。我喜欢这个想法……但经过几天的故障排除后,却感觉效率不高。
public Bid() {
User = new ApplicationUser();
Listing = new Listing();
}
public Listing() {
User = new ApplicationUser();
Bids = new List<Bid>();
}
编辑。上面的代码是错误的。删除这些初始化项。它们应该只用于集合。你得到这些奇怪的错误的原因是因为每次你加载Bid
或Listing
对象时,你正在创建一个缺少必要参数的全新对象,因此当调用savechanges时,你最终会与EF抱怨某些必需的参数丢失。
我最初认为这是Bid
类的属性。
public int ListingID
但是你有…
bid.Listing = null;
从逻辑上讲,这没有任何意义。在第一行代码中,您说每个出价都需要Listing
属性。但是通过将其设置为null,您表示"此列表不是此出价所必需的"。
我认为你可以安全地删除你设置导航属性为null的代码行,因为它们没有完成任何事情,因为你只是删除Bid
对象。
我有一个类似的问题,对我来说,看起来我没有正确地在各自的类中建立父级和子级之间的关系。
我的修复方法是将下面指定的属性添加到Child类中,用于表示其父类Id的属性
public class Child
{
[Key, Column(Order = 1)]
public string Id { get; set; }
[Key, ForeignKey("Parent"), Column(Order = 2)] // adding this line fixed things for me
public string ParentId {get; set;}
}
public class Parent
{
[Key, Column(Order = 1)]
public string Id { get; set; }
...
public virtual ICollection<Child> Children{ get; set; }
}
查看您的代码,它看起来像在Bid类中,它的父类是ListingId?
如果是这样,那将是要修改的行,如下所示:
[Key, ForeignKey("Listing"), Column(Order = 2)]
public int ListingID { get; set; }
这样做之后,我也能够删除下面的行,所以只需要。remove调用:
db.Entry(bid).State = EntityState.Deleted;