我有一个非常简单的类似拍卖的应用程序。在尝试从父级(清单)中删除子级(Bid)时,使用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()
}
}
直到我取消了bid.Listing,我得到了一个DbEntityValidationException,说明列表的字段是必需的。在调试器中浏览它会显示EF尝试将 new 实体添加到bid.User和bid.Listing。疯了......但还行。我一直跟着它走了,结果你看到了上面的内容......这导致另一个xxx:
UserName字段是必需的。
UserName位于IdentityUser(AspNetUsers表)中,作为Identity Framework的一部分。
它还在尝试添加一个ApplicationUser ......某种程度上,某个地方?我在上面查询的图表中没有任何地方存在ApplicationUser对象。我只是没有看到它。
检查表格显示的字段与上面的实体完全相同。
这是我的第一个非平凡的Code-First项目。我曾经在一些相当大的DB-First项目中使用edmx模型,并且永远不会记得遇到这么多障碍和奇怪的问题&#34;陷入困境。大多数事情似乎都有效。我应该转换这个东西吗?我已经浪费了太多时间在这么简单的事情上。我想要EF。经过几天的故障排除后,我喜欢它的想法......但感觉不是特别有效。
提前致谢。
答案 0 :(得分:1)
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
对象。
答案 1 :(得分:0)
我有一个类似的问题,对我来说,我好像没有正确建立父母和孩子在各自班级之间的关系。
我的解决方法是将以下指定的属性添加到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;