18

I want update family of a person who his name is pejman. This is my object Class:

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; }
}

and my method for updating is: (in 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();
    }
}

but it doesn't work! what is the problem?

EDIT: assume that i don't know person's Id, and i just know person's name, is there any way to update person's family?

kame
  • 20,848
  • 33
  • 104
  • 159
pmn
  • 2,176
  • 6
  • 29
  • 56

5 Answers5

26

You are missing an Id field when creating an instance of Person object. Because of this Entity Framework is not able to find an existing Person.

Your code should look like this:

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();
    }
kame
  • 20,848
  • 33
  • 104
  • 159
Paweł Bejger
  • 6,176
  • 21
  • 26
  • Thanks.. but assume i don't know id of person and i just know person's name! is there any way to update my record by the name? – pmn Jan 25 '14 at 13:10
  • 1
    Why don't you know the ID? It's a lot easier if you do. What if there are multiple persons with the same name? – CodeCaster Jan 25 '14 at 13:12
  • 1
    Its just a test programm.. maybe in some project i want update some record by using postalCode column! I want a way to update according to unique column, not only key column – pmn Jan 25 '14 at 13:18
  • 1
    Sure, but before you begin updating you should already have the entity (instance of person that you previously retrieved from the db, that that the db can locate via its key) see below. – Guy Apr 10 '15 at 07:45
2

EDIT: assume that i don't know person's Id, and i just know person's name, is there any way to update person's family?

I'm assuming that the FirstName field of Person class contains the person's name, and updating the person's family means updating the LastName field.

The first step is to get all Person records with FirstName equals the person's name, let's say it's "pejman" so the code would be as below.

var personsToUpdate = newContext.Persons.Where(o => o.FirstName == "pejman");

The next step is enumerate personsToUpdate and set the LastName property to the family name you want, then call .SaveChanges() method of the DbContext to submit the changes to the database. Let's say you want to update the person's family name to "MyFamilyName", the code would be as below

foreach (Person p in personsToUpdate)
{
    p.LastName = "MyFamilyName";
}

newContext.SaveChanges();

The following is the modified code of your Update method with the name and family parameter.

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();
    }
}
ekad
  • 14,436
  • 26
  • 44
  • 46
2

For resolving this error i got values by ID from database stored in Var Temprc. Then updated the field Password which i wont to update. Then attached temprc to my Userregistrations model. Then Marked PasswordConfirm isModified. then Savechanges();

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();    
                }
kame
  • 20,848
  • 33
  • 104
  • 159
Saineshwar Bageri - MVP
  • 3,851
  • 7
  • 41
  • 47
0

assuming you have the instance of Person that the db can find (as mentioned by 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; }
    }

see as well update a single field in Entity Framework and Entity Framework update single

Community
  • 1
  • 1
Guy
  • 1,232
  • 10
  • 21
-2

The following worked for me:

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);
}
LittleBobbyTables - Au Revoir
  • 32,008
  • 25
  • 109
  • 114