实体框架6.x无法删除关系

时间:2016-06-26 23:08:23

标签: c# entity-framework ef-code-first asp.net-identity

我有一个非常简单的类似拍卖的应用程序。在尝试从父级(清单)中删除子级(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。经过几天的故障排除后,我喜欢它的想法......但感觉不是特别有效。

提前致谢。

2 个答案:

答案 0 :(得分:1)

public Bid() {
    User = new ApplicationUser();
    Listing = new Listing();
}

public Listing() {
    User = new ApplicationUser();
    Bids = new List<Bid>();
}

编辑。上面的代码是错的。删除那些初始化程序。它们应仅存在于集合中。您收到这些奇怪错误的原因是因为每次加载BidListing对象时,您都会创建缺少必需参数的全新对象,因此在调用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;