簡體   English   中英

無法更新實體框架 6 中的外鍵

[英]Unable to update Foreign Key in Entity Framework 6

我正在嘗試對外鍵進行簡單的更新,但腳本永遠不會被發送。

這是我正在使用的代碼:

using (var db = new MyContext())
{
      db.Entry<Contact>(newContact).State = EntityState.Modified;
      newContact.ContactOwner = db.Person.Find(3);
      db.SaveChanges();
}

EF6 更新 Persons 表中列的其余部分,但不會更新 Persons 表中的 Contact_Id。

個人實體:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Contact> ContactList { get; set; }
}

聯系實體:

public class Contact
{
    public int Id { get; set; }
    public string Email { get; set; }
    public string TelNo { get; set; }
    public Person ContactOwner { get; set; }
}

我在這里缺少什么?

請幫忙!

由於您正在與獨立協會合作。 你可以

  • ContactList添加和刪​​除關系,但您需要從兩個Person檢索。

     db.Entry(newContact).State = EntityState.Modified; var p1 = db.Set<Person>().Include(p => p.ContactList) .FirstOrDefault(p =>p.Id == 1); p1.ContactList.Remove(newContact); var p3 = db.Set<Person>().Include(p => p.ContactList) .FirstOrDefault(p => p.Id == 3); p3.ContactList.Add(newContact); db.SaveChanges();
  • 或者您可以使用斷開連接的對象,但您需要手動管理關系。

     db.Entry(newContact).State = EntityState.Modified; var p1 = new Person { Id = 1 }; db.Entry(p1).State = EntityState.Unchanged; var p3 = new Person { Id = 3 }; db.Entry(p3).State = EntityState.Unchanged; var manager = ((IObjectContextAdapter)db).ObjectContext.ObjectStateManager; manager.ChangeRelationshipState(newContact, p1, item => item.ContactOwner, EntityState.Deleted); manager.ChangeRelationshipState(newContact, p3, item => item.ContactOwner, EntityState.Added); db.SaveChanges();

聚苯乙烯

您可能需要重新考慮添加外鍵值,以簡化一切,只需提及 Id 即可更新外鍵。

有關更多信息,請參閱此帖子

這就是我最終構建到凌晨的東西,應該/應該再重構一些......

   protected static async Task<int> SaveEntity<t>(t obj) where t : BaseModel
    {
        try
        {
            using (DatabaseContext db = GetDbContext())
            {

                //get the basemodel/fk reference properties
                IEnumerable<PropertyInfo> props = obj.GetType().GetProperties().Where(p => p.PropertyType.BaseType == typeof(BaseModel));

                if (obj.Id <= 0)
                {//insert

                    db.Entry(obj).State = EntityState.Added;

                    //set fk reference props to unchanged state
                    foreach (PropertyInfo prop in props)
                    {
                        Object val = prop.GetValue(obj);
                        if (val != null)
                        {
                            db.Entry(val).State = EntityState.Unchanged;
                        }
                    }

                    //do insert
                    return await db.SaveChangesAsync();

                }
                else
                {//update

                    //get the posted fk values, and set them to null on the obj (to avaid dbContext conflicts)
                    Dictionary<string, int?> updateFKValues = new Dictionary<string, int?>();
                    foreach (PropertyInfo prop in props)
                    {
                        BaseModel val = (BaseModel)prop.GetValue(obj);
                        if (val == null)
                        {
                            updateFKValues.Add(prop.Name, null);
                        }
                        else
                        {
                            updateFKValues.Add(prop.Name, val.Id);
                        }

                        prop.SetValue(obj, null);
                    }

                    //dbContext creation may need to move to here as per below working example
                    t dbObj = (t)db.Set(typeof(t)).Find(new object[] { obj.Id }); //this also differs from example

                    //update the simple values
                    db.Entry(dbObj).CurrentValues.SetValues(obj);

                    //update complex values
                    foreach (PropertyInfo prop in props)
                    {
                        Object propValue = null;
                        if (updateFKValues[prop.Name].HasValue)
                        {
                            propValue = (BaseModel)db.Set(prop.PropertyType).Find(new object[] { updateFKValues[prop.Name] });
                        }

                        prop.SetValue(dbObj, propValue);
                        if (propValue != null)
                        {
                            db.Entry(propValue).State = EntityState.Unchanged;
                        }

                    }

                    //do update
                    return await db.SaveChangesAsync();

                }

            }
        }
        catch (Exception ex)
        {
            ExceptionHelper.Log(ex);
            throw;
        }
    }

基本上發生這種情況是因為EntryState.Modified只是尋找標量屬性(原始類型)並且具有獨立關聯(您的情況),您沒有它。

有幾種方法可以實現這一點,@Yuliam 指出了其中的一些,在這里您可以找到更多。

當需要更新主對象及其附加的外鍵對象時,此解決方案對我有用。

    public virtual async Task<Result<TEntity>> Update<TEntity>(TEntity entity) where TEntity : class
    {
        Result<TEntity> returnResult = new Result<TEntity>();

        try
        {
            //get the fk reference properties
            IEnumerable<PropertyInfo> props = entity.GetType().GetProperties().Where(p => p.PropertyType.BaseType == typeof(object));

            //set fk reference props to modified state
            foreach (PropertyInfo prop in props)
            {
                Object val = prop.GetValue(entity);
                if (val != null)
                {
                    dbContext.Entry(val).State = EntityState.Modified;
                }
            }


            dbContext.Entry(entity).State = EntityState.Modified;
            await dbContext.SaveChangesAsync();
            returnResult.SetSuccess(result: entity);
        }
        catch (Exception e)
        {
            log.Error(e);
            returnResult.SetError(exception: e);
        }
        
        return returnResult;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM