I am trying to implement entity framework 6 in my application, but I have a problem performing updates on the records.
If I have 2 records in the database, lets say:
| Id | Name | Lastname |
|---|---|---|
| 1 | Jason | Momoa |
| 2 | Aqua | Man |
Then I alter the one with id 1 from "Jason" to "Water" and call the UpdatePerson function, with a new Person object that has the same primary key.
The result will be:
| Id | Name | Lastname |
|---|---|---|
| 1 | Water | Momoa |
| 2 | Water | Momoa |
WHY should that be the result?? I was already looking around for a solution but could not find any clue. Anyone an idea what I am doing wrong?
As far as I understood the disconnected datacontext I used, can simply update a record with the knowledge of the primary key.
For reference the page for EF6
My code looks like this:
public class Person
{
private int _id = -1;
private string _name;
private string _lastname;
public int PersonId { get => _id; set => _id = value; }
[Required]
[MaxLength(255)]
public string Name { get => _name; set => _name = value; }
[Required]
public string Lastname { get => _lastname; set => _lastname = value; }
}
DbContext:
public partial class Model1 : DbContext
{
public Model1() : base("name=entity_test") { }
public DbSet<Person> People { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Person>().MapToStoredProcedures();
}
}
public class PersonModel
{
public ObservableCollection<Person> GetPeople()
{
using (Model1 context = new Model1())
{
var list = context.People.AsNoTracking().ToList();
if (list == null)
return null;
return new ObservableCollection<Person>(list);
}
}
public void AddPerson(Person person)
{
using (Model1 context = new Model1())
{
context.People.Add(person);
context.SaveChanges();
}
}
public void UpdatePerson(Person person)
{
using (Model1 context = new Model1())
{
context.Entry(person).State = EntityState.Modified;
context.SaveChanges();
}
}
}
EDIT
Tables were not displayed nicely.
EDIT 2
Here the rest of the code and the output of context.Database.Log = s => Console.WriteLine(s);
Output:
`Person_Update`
-- PersonId: '1' (Type = Int32, IsNullable = false)
-- Name: 'Water' (Type = String, IsNullable = false, Size = 5)
-- Lastname: 'Momoa' (Type = String, IsNullable = false, Size = 5)
-- Executing at 29.10.2021 16:46:05 +02:00
-- Completed in 198 ms with result: 2
Code:
public class NotifyBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(field, newValue))
{
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
}
return false;
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
PersonModel model = new PersonModel();
if (DataContext is ViewModel vm)
{
vm.AddModifyPerson();
}
}
}
public class ViewModel : NotifyBase
{
public ViewModel()
{
MiniProfilerEF6.Initialize();
model = new PersonModel();
using (var db = new Model1())
{
// create if not exists
if (db.Database.CreateIfNotExists())
{
Console.WriteLine();
}
People = model.GetPeople();
}
}
private PersonModel model;
private ObservableCollection<Person> people = new ObservableCollection<Person>();
private Person currentPerson = new Person();
public ObservableCollection<Person> People { get => people; set => SetProperty(ref people, value); }
public Person CurrentPerson { get => currentPerson; set => SetProperty(ref currentPerson, value); }
public void AddModifyPerson()
{
if (CurrentPerson.PersonId == -1)
{
model.AddPerson(CurrentPerson);
}
else
{
model.UpdatePerson(
new Person()
{
PersonId = CurrentPerson.PersonId,
Lastname = CurrentPerson.Lastname,
Name = CurrentPerson.Name,
});
}
People = model.GetPeople();
}
}
Edit 3
Code for from miniprofiler
public void UpdatePerson(Person person)
{
var profiler = MiniProfiler.StartNew("My Profiler");
using (MiniProfiler.Current.Step("Update_Sql"))
{
using (Model1 context = new Model1())
{
context.Entry(person).State = EntityState.Modified;
context.SaveChanges();
}
}
Console.WriteLine(MiniProfiler.Current.RenderPlainText());
}
EDIT 4
output of an update call from mysql.general_log
| command_type | argument |
|---|---|
| Init DB | entity_test |
| Query | SET TRANSACTION ISOLATION LEVEL REPEATABLE READ |
| Query | BEGIN |
| Query | CALL Person_Update(1, 'Jason1', 'Momoa') |
| Query | COMMIT |
It does look like the update procedure is not performing the where clause. If I run call Person_Update_Custom(1, 'test','tes') in the workbench all rows are updated. Here is the stored procedure:
CREATE DEFINER=`root`@`localhost` PROCEDURE `Person_Update`(IN PersonId int,IN Name varchar(255) ,IN Lastname longtext)
BEGIN
UPDATE `People` SET `Name`=Name, `Lastname`=Lastname WHERE `PersonId` = PersonId;
END