如何使用Entity Framework更新特定记录的一个字段?

18

我想更新一个名叫Pejman的人的家庭信息。这是我的对象类:

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set;}
    public DateTime BirthDate { get; set; }
    public bool IsMale { get; set; }
    public byte[] Image { get; set; }
    public byte[] RowVersion { get; set; }
    public virtual Person Parent { get; set; }
    public virtual ICollection<PhoneNumber> PhoneNumber { get; set; }
    public virtual ICollection<Address> Addresses { get; set; }
    public virtual PersonInfo PersonInfo { get; set; }
}

我的更新方法是:(在Program.cs中)

public static void Update(string name, string family)
{
    var _person = new Person() { FirstName = name, LastName = family };

    using (var newContext = new MyDbContext())
    {
        newContext.Persons.Attach(_person);
        newContext.Entry(_person).Property(X => X.LastName).IsModified = true;
        newContext.SaveChanges();
    }
}

但它不起作用!问题出在哪里?

编辑:假设我不知道人的ID,我只知道人的名字,有没有办法更新人的家庭信息?

5个回答

26

创建Person对象实例时缺少Id字段,因此Entity Framework无法找到现有的Person。

您的代码应该像这样:

public static void Update(int id, string name, string family)
{
    var _person = new Person() { Id = id , FirstName = name, LastName = family };

    using (var newContext = new MyDbContext())
    {
        newContext.Persons.Attach(_person);
        newContext.Entry(_person).Property(X => X.LastName).IsModified = true;
        newContext.SaveChanges();
    }

谢谢,但是假设我不知道这个人的ID,只知道他的名字!有没有办法通过名字更新我的记录? - pejman
1
你为什么不知道这个ID呢?如果你知道的话,会容易很多。如果有多个人名字相同怎么办? - CodeCaster
1
这只是一个测试程序...也许在某个项目中,我想通过使用postalCode列更新一些记录!我想要一种根据唯一列而不仅仅是关键列进行更新的方法。 - pejman
1
当然可以,但在开始更新之前,您应该已经拥有实体(先前从数据库检索到的人员实例,数据库可以通过其键定位)请参见下文。 - Guy

2
为解决这个错误,我从数据库中按ID获取了存储在Var Temprc中的值。 然后更新了我想要更新的密码字段。 然后将temprc附加到我的Userregistrations模型上。 然后标记PasswordConfirm为已修改。 最后保存更改。
using (var db = new Entities())
                {                       
                    var temprc = _reg.GetUserByID(Convert.ToInt32(Session["LogedUserID"]));
                    temprc.PasswordConfirm = U.NewPassword;
                    db.Userregistrations.Attach(temprc);
                    db.Entry(temprc).Property(x => x.PasswordConfirm).IsModified = true;
                    db.SaveChanges();    
                }

2
我假设Person类中的FirstName字段包含人的姓名,更新该人的家庭意味着更新LastName字段。首先,需要获取所有FirstName等于该人名字的Person记录,假设该名字为"pejman",则代码如下所示。
var personsToUpdate = newContext.Persons.Where(o => o.FirstName == "pejman");

下一步是枚举personsToUpdate并将LastName属性设置为您想要的姓氏,然后调用DbContext.SaveChanges()方法将更改提交到数据库。假设您想将人的姓氏更新为"MyFamilyName",则代码如下所示。
foreach (Person p in personsToUpdate)
{
    p.LastName = "MyFamilyName";
}

newContext.SaveChanges();

以下是您的Update方法的修改后代码,包含namefamily参数。
public static void Update(string name, string family)
{
    using (var newContext = new MyDbContext())
    {
        // get all Persons with FirstName equals name
        var personsToUpdate = newContext.Persons.Where(o => o.FirstName == name);

        // update LastName for all Persons in personsToUpdate
        foreach (Person p in personsToUpdate)
        {
            p.LastName = family;
        }

        newContext.SaveChanges();
    }
}

0
假设您已经有了数据库可以找到的Person实例(如Paweł Bejger所提到的):
public class Person
    {
        /// <summary>
        /// USAGE: await UpdateDbEntryAsync(myPerson, d => d.FirstName, d => d.LastName);
        /// </summary>
        async Task<bool> UpdateDbEntryAsync<T>(T entity, params Expression<Func<T, object>>[] properties) where T : class
        {
            try
            {
                var db = new RtTradeData.Models.ApplicationDbContext();
                var entry = db.Entry(entity);
                db.Set<T>().Attach(entity);
                foreach (var property in properties)
                    entry.Property(property).IsModified = true;
                await db.SaveChangesAsync();
                return true;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("UpdateDbEntryAsync exception: " + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// The idea is that SomeFunction already has the instance of myPerson, that it wants to update.
        /// </summary>
        public void SomeFunction()
        {
            myPerson.FirstName = "Another Name"; myPerson.LastName = "NewLastName";
            UpdateDbEntryAsync(myPerson, d => d.FirstName, d => d.LastName);
        }
        /// <summary>
        /// Or directly requesting the person instance to update its own First and Last name...
        /// </summary>
        public void Update(string firstName, string lastName)
        {
            FirstName = "Another Name"; LastName = "NewLastName";
            UpdateDbEntryAsync(this, d => d.FirstName, d => d.LastName);
        }

        Person myPerson = new Person { PersonId = 5, FirstName = "Name", LastName = "Family" };
        public int PersonId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

请查看在Entity Framework中更新单个字段Entity Framework更新单个字段


-2

以下方法对我有效:

public ActionResult ChangePassword(Account account)
{
    try
    {
            if (ModelState.IsValid)
            {
                db.Accounts.Attach(account);
                db.Entry(account).Property(x => x.Password).IsModified=true;
                db.Configuration.ValidateOnSaveEnabled = false;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
    }
    catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
    {
        Exception raise = dbEx;
        foreach (var validationErrors in dbEx.EntityValidationErrors)
        {
            foreach (var validationError in validationErrors.ValidationErrors)
            {
                string message = string.Format("{0}:{1}",
                    validationErrors.Entry.Entity.ToString(),
                    validationError.ErrorMessage);
                raise = new InvalidOperationException(message, raise);
            }
        }
        ModelState.AddModelError("", raise);

    } 
    return View(account);
}

5
太棒了,一段没有解释为什么会起作用或如何解决问题的代码。 - Maarten
你从另一个帖子中得到了这个答案,我记得这个帖子。 - CyberNinja

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接