如何在EF中更新子项并在一对多关系中插入新子项

时间:2012-12-28 23:36:03

标签: entity-framework one-to-many foreign-key-relationship

我在ItemPrice和ItemPriceHistory类之间有一对多关系,我的映射如下:

public class ItemPrice 
{
    public long ID {get; set;}
    public List<ItemPriceHistory> ItemPriceHistories { get; set; }

    public ItemPrice()
    {
       ItemPriceHistories = new List<ItemPriceHistory>();
    }
}

public class ItemPriceHistory
{
    public ItemPrice ItemPrice { get; set; }
    public long ID {get; set;}
    public bool IsCurrent { get; set; }
}


modelBuilder.Entity<ItemPriceHistory>()
            .HasRequired(h => h.ItemPrice)
            .WithMany(p => p.ItemPriceHistories)
            .Map(h => h.MapKey("ItemPrice_ID"));

我正在尝试更新以前的ItemPriceHistory条目并尝试添加新的ItemPriceHistory条目。

    var dbItemPrice = repo.Std.Get<ItemPrice>()
                                    .SingleOrDefault(c => c.ID == id);                

            if (dbItemPrice == null)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }                

            //query for matching ItemPriceHistory
            var dbPriceHistories = repo.Std.Get<ItemPriceHistory>()
                                    .Include(h=>h.ItemPrice, repo.Std)
                                    .Where(h => h.ItemPrice.ID == ItemPrice.ID)
                                    .OrderByDescending(h => h.ModifiedDate);

            #region new history entry

            var newHistoryEntry = new ItemPriceHistory();
            newHistoryEntry.IsCurrent = true;
            newHistoryEntry.ItemPrice = dbItemPrice;

            //copy the current pirce list and update it with new history entry
            var currentPriceHistoryList = dbPriceHistories.ToList();
            currentPriceHistoryList.ForEach(h => { h.IsCurrent = false; });
            currentPriceHistoryList.Add(newHistoryEntry);

            //new price list
            var newHistoryList = new List<ItemPriceHistory>();
            currentPriceHistoryList.ForEach(h => newHistoryList.Add(new ItemPriceHistory
                                            {
                                                ItemPrice = h.ItemPrice,
                                                IsCurrent = h.IsCurrent,
                                            }
                                    ));
            #endregion

            //delete current price histories
            dbItemPrice.ItemPriceHistories.Clear(); 


            // add histories to database
            newHistoryList.ForEach(h => dbItemPrice.ItemPriceHistories.Add(h));

            Context.SaveChanges();

当它调用SaveChanges()时,我收到以下错误:

  

{&#34;保存不公开外来实体的实体时发生错误   他们关系的关键属性。 EntityEntries属性   将返回null,因为无法将单个实体标识为   异常的来源。保存时可以处理异常   通过在实体类型中公开外键属性使其变得更容易。   有关详细信息,请参阅InnerException。&#34;}

     

InnerException:{&#34;来自&#39; ItemPriceHistory_ItemPrice&#39;的关系   AssociationSet位于&#39;已删除&#39;州。鉴于多样性   约束,一个相应的ItemPriceHistory_ItemPrice_Source&#39;必须   也在“已删除”中。 。状态&#34;}

我不想删除我的ItemPrice_Source。我只想删除当前的ItemPriceHistories并更新之前的ItemPriceHistories并添加新的ItemPriceHistory条目。如何安全地更新ItemPriceHistory条目以及新的ItemPriceHistory条目?

谢谢!

2 个答案:

答案 0 :(得分:0)

我使用了一个适合您的STD通用存储库类的示例。 看起来你正在使用这种模式。

你有没有试过像

这样的东西
 public virtual IQueryable<T> GetList(Expression<Func<T, bool>> predicate, bool withTracking = false)
    {
        if (withTracking)
            return QuerySet.Where(predicate);
        return QuerySet.Where(predicate).AsNoTracking();
    }


//    then
var iph_list = RepItemPriceHist.GetList(h=>h.ItemPrice.Id == VarID)

 //  psuedo code... foreach history entity entitity.Iscurrent = false;

所以现在这些实体应该由州经营者进行更改和管理。 添加新条目......

// add histories to database
          newHistoryList.ForEach(h => dbItemPrice.ItemPriceHistories.Add(h));
 Context.SaveChanges();

我不明白为什么你需要 CLEAR 这个集合 您是否更新现有记录并添加新记录? 祝你好运

答案 1 :(得分:0)

您无法只加载ItemPrice 包括所有当前ItemPriceHistories,然后将这些历史记录的IsCurrent标记设置为false和使用IsCurrent = true添加新记录?更改跟踪应更新当前历史记录并将新的历史记录插入数据库:

var dbItemPrice = repo.Std.Get<ItemPrice>()
    .Include(i => i.ItemPriceHistories, repo.Std)
    .SingleOrDefault(i => i.ID == id);                

if (dbItemPrice == null)
    return Request.CreateResponse(HttpStatusCode.NotFound);

foreach (var history in dbItemPrice.ItemPriceHistories)
    history.IsCurrent = false;

dbItemPrice.ItemPriceHistories.Add(new ItemPriceHistory { IsCurrent = true });

Context.SaveChanges();