У меня есть сущность Contracts
, как это:
public partial class Contracts
{
public Contracts()
{
ListKindWorks = new HashSet<ListKindWorks>();
ListSubjects = new HashSet<ListSubjects>();
}
public int Id { get; set; }
public string Num { get; set; }
public DateTime DateConclusion { get; set; }
public int Worker { get; set; }
public DateTime DateStartWork { get; set; }
public DateTime DateEndWork { get; set; }
public float Salary { get; set; }
public virtual Workers WorkerNavigation { get; set; }
public virtual ICollection<ListKindWorks> ListKindWorks { get; set; }
public virtual ICollection<ListSubjects> ListSubjects { get; set; }
}
И функция ShowUpdateDialog()
:
/// <summary>
/// Open dialog for update chosen Contract
/// </summary>
/// <param name="c">chosen Contract</param>
internal void ShowUpdateDialog(Contracts c)
{
Contract = c;
using (ContractForm form = new ContractForm())
{
form.Fill(model.Data);
form.Fill(Contract);
form.Fill(model.GetUI(Mode.UPDATE));
if (form.ShowDialog() == DialogResult.OK)
{
bool result = true;
try
{
using (ModelContext context = new ModelContext())
{
context.Attach(Contract);
Contract = form.GetMainValues(Contract);
Contract = form.GetDetailValues(Contract);
context.SaveChanges();
}
}
catch (Exception ex)
{
result = false;
string msg = string.Format("Ошибка во время обновления записи в базе данных. Детали: {0}", ex.Message);
form.ShowError(msg);
}
if (result)
{
ContractUpdatedSuccessEvent?.Invoke(this, EventArgs.Empty);
}
}
}
}
Внешняя переменная:
public Contracts Contract { get; set; }
Этоиспользуется для того, чтобы не выделять память каждый раз, и является общедоступной, поэтому в случае успешного обновления другой класс может взять ее и вставить в DataGridView.Поэтому я не обращаюсь к базе данных для текущих значений записи, потому что данные поступают из DataGridView.Для отслеживания изменений используется context.Attach(Contract)
.
internal Contracts GetMainValues(Contracts c)
{
c.Num = tbNum.Text;
c.Salary = float.Parse(tbSalary.Text);
c.DateConclusion = dpDateConclusion.Value;
c.DateStartWork = dpDateStart.Value;
c.DateEndWork = dpDateEnd.Value;
Item item = (Item)cbWorker.SelectedItem;
c.Worker = item.Id;
return c;
}
internal Contracts GetDetailValues(Contracts c)
{
listKindWorks.Clear();
listSelectedSubjects.Clear();
foreach (int index in clbKindWork.CheckedIndices)
{
int id = ((Item)clbKindWork.Items[index]).Id;
ListKindWorks item = new ListKindWorks
{
IdContract = c.Id,
IdKindWork = id
};
listKindWorks.Add(item);
}
foreach (Item item in lbSelectedSubject.Items)
{
ListSubjects subject = new ListSubjects
{
IdContract = c.Id,
IdSubject = item.Id
};
listSelectedSubjects.Add(subject);
}
c.ListKindWorks = listKindWorks;
c.ListSubjects = listSelectedSubjects;
return c;
}
Моя проблема заключается в следующем:
Когда if (.. == DialogResult.OK)
имеет значение true, мне нужно обновить текущий Contract
для новых значений из form
, например:
context.Attach(Contract);
Contract = form.GetMainValues(Contract);
Contract = form.GetDetailValues(Contract);
context.SaveChanges();
Но поэтому этот код должен быть в using (ContractForm..)
.В противном случае невозможно получить новые значения из form
.Если я создаю новую переменную, например Contracts
, и отдельную функцию Update
, например, так:
private void Update(Contracts c)
{
using (ModelContext context = new ModelContext())
{
context.Attach(Contract);
Contract = c;
context.SaveChanges();
}
}
Обновление значений из GetDetailValues()
не происходит.Зачем?
Можно ли упростить этот код?
Обновление:
Согласно коду из ответа Хенк Холтерман и мои private void Update(Contracts c)
:
изменили значения с GetMainValues()
, но не с GetDetailValues()