不为其关系公开外键属性的实体出错

Posted

技术标签:

【中文标题】不为其关系公开外键属性的实体出错【英文标题】:Error with entities that do not expose foreign key properties for their relationships 【发布时间】:2011-03-23 16:43:25 【问题描述】:

我花了一些时间来构建我的领域模型(使用 EF CTP5 代码优先),现在我想我应该通过一些测试数据看看是否一切正常。不幸的是,我的应用程序似乎加载了除了运行时之外不会被捕获的错误,因为一切都可以完美编译。无论如何,我不断收到以下错误:

保存时出错 不暴露外国的实体 他们的关键属性 关系。

这是内部异常:

"INSERT 语句与 FOREIGN KEY 约束 \"Item_ItemStatus\"。冲突 发生在数据库“CFShawe”中, 表 \"dbo.ItemStatus\",列 'Id'。\r\n语句已被 终止。”

我不知道为什么会这样。我怀疑这可能是由我在 Seed() 方法中加载数据库的所有静态内容的初始化程序类引起的。所以我评论了我添加 ItemStatuses 的部分,但我仍然遇到同样的错误。此外,我应该在编译时得到这个,而不是在运行时,不是吗?

下面是 ItemStatus 类和我的部分测试数据:

public class ItemStatus

 public int Id  get; set; 
 public string Description  get; set; 
 public ICollection<Item> Items  get; set; 


//Test data inside the Index() method of the ItemsController
var item2 = new Item
  
   Title = "iPhone 4",
   Description = "Lorem Ipsum is simply",
   StartingPrice = 400f,
   User = user2,
   Status = 1,
   EndDate = DateTime.Now.AddDays(10),
   StartDate = DateTime.Now,
   BidIncrement = 3f,
   Bids = new List<Bid>(),
   Comments = new List<Comment>(),
   //ItemStatus = _itemsService.GetItemStatusById(1),    
   ViewingUsers = new List<User>(),
   WatchingUsers = new List<User>(),
   Tags = new List<Tag>()
  ;
  //here's where I save the data to the database
  var category = _categoryService.GetChildByName(categoryName);
  category.Items.Add(item2);
  _categoryService.Save();

更新:(由 Slauma 要求)

public class Item

    public int Id  get; set; 
    public string Title  get; set; 
    public string Description  get; set; 
    public float StartingPrice  get; set; 
    public float? BidIncrement  get; set; 
    public DateTime StartDate  get; set; 
    public DateTime EndDate  get; set; 
    public int Status  get; set; 
    [ForeignKey("Status")]
    public virtual ItemStatus ItemStatus  get; set; 
    public virtual Address PickupAddress  get; set; 
    public virtual User User  get; set; 
    public virtual ChildCategory Category  get; set; 
    public virtual ICollection<Comment> Comments  get; set; 
    public virtual ICollection<Image> Images  get; set; 
    public virtual ICollection<Bid> Bids  get; set; 
    public virtual ICollection<User> WatchingUsers  get; set; 
    public virtual ICollection<User> ViewingUsers  get; set; 
    public virtual ICollection<Tag> Tags  get; set; 
    //public virtual ItemRating Rating  get; set; 

    public bool IsValidBidAmount(int amount)
    
        if (amount <= this.Bids.Max(a => a.Amount))
            return false;

        return true;
    

    public bool IsClosed()
    
        if (this.ItemStatus.Id.Equals(3))
            return true;
        return false;
    

    public bool IsPending()
    
        if (ItemStatus.Id.Equals(2))
            return true;
        return false;
    

    public bool IsPublished()
    
        if (ItemStatus.Equals(1))
            return true;
        return false;
    

    public int WinnerId()
    
        if(IsClosed())
        
            User highestBidder = null;
            foreach (Bid b in Bids)
            
                if (b.Amount.Equals(HighestBid()))
                    highestBidder = b.User;
            
            if (highestBidder != null) return highestBidder.Id;
        
        return 0;
    

    public float HighestBid()
    
        return Bids.Max(u => u.Amount);
    

    public string MainImageLink()
    
        var mainImage = Images.Single(i => i.Rank.Equals(0));
        return mainImage.Path;
    

    public string FirstTag()
    
        return Tags.First().Title;
    

更新 2:

public class UnitOfWork : IUnitOfWork

    private readonly IDatabaseFactory _databaseFactory;
    private DbContext _context;
    public UnitOfWork(IDatabaseFactory dbFactory)
    
        _databaseFactory = dbFactory;
    

    protected DbContext DataContext
    
        get
        
            return _context ?? (_context = _databaseFactory.GetDbContext());
        
    

    public void Commit()
    
        DataContext.SaveChanges();
    


public class EfDatabaseFactory : IDisposable, IDatabaseFactory

    private SharweEntities _dbContext;


    public DbContext GetDbContext()
    
        return _dbContext ?? (_dbContext = new SharweEntities());
    

    public System.Data.Objects.ObjectContext GetObjectContext()
    
        return _dbContext.ObjectContext;
    

    public void Dispose()
    
        if (_dbContext != null)
            _dbContext.Dispose();
    

对这件事有什么想法吗?提前致谢。

【问题讨论】:

您在哪里/如何管理您的 DBContext? 您展示了很多代码,但没有任何与您的问题相关的代码。除了ItemStatus 和创建Item 和ItemStatus 的代码,将其添加到DbContext 并调用SaveChanges 之外,Item 类也会很有帮助。此外,如果您在模型类属性上放置了属性,或者您是否使用 Fluent API 以及如何自定义模型。并删除这个 Lore ipsum 和图像的东西...... @Derek Beattie:我正在使用 UnitOfWork 来管理 DbConext。在上面的 sn-p (我已经编辑过)中,我调用 categoryService 上的 Save() 方法,该方法调用 unitOfWork.Commit() 反过来又调用 context.SaveChanges() @Slauma:我已经更新了我的帖子并添加了我已经拥有的代码。您认为问题出在我使用 DataAnnotations 标记为 FK 的 Status 属性上吗? @Kassem:你的 FK 属性说,int StatusItemStatus 表的 FK。由于它不可为空,因此它是必需的关系。在保存Item2 之前设置Status=1。所以,问题:数据库中是否有ItemStatus 行与Id = 1 【参考方案1】:

我认为错误表明您的数据库中没有 ID = 1 的 ItemStatus 记录。

【讨论】:

我遇到了同样的问题,请检查一下。***.com/questions/17085329/tryupdatemodel-error

以上是关于不为其关系公开外键属性的实体出错的主要内容,如果未能解决你的问题,请参考以下文章

更新实体时出现异常“无法更改关系,因为一个或多个外键属性不可为空”

mysql数据库,外键约束和表关系

理解实体框架核心外键关系

Entity Framework Core 实体关系的配置

Entity Framework Core 实体关系的配置

ER-Studio的五种关系说明