Два (почти) идентичных обработчика Button-Click в C # / Entity Framework ведут себя по-разному - PullRequest
0 голосов
/ 02 июня 2018

Это только мой второй пост, прошу прощения за любые ошибки протокола.

У меня есть два обработчика Button-Click, которые почти копируют и вставляют изображения, но имеют различия в поведении, которые вызывают проблемы (и разочарование)

Оба добавляют новые дочерние записи в базу данных сотрудников (Entity Framework 6, Code First), один новый номер телефона, другой - должность.

Номер телефона:

private void btn_NewRecord_Click(object sender, EventArgs e)
{
    if (thisNumber != null)
    {
        DbEntityEntry entry = _fDBC.Entry(thisNumber);

        if (entry.State == EntityState.Modified)
        {
               //  PROMPT to Save or Cancel current modified record
        }
    }

    EmployeePhoneNumber newNumber = new EmployeePhoneNumber();
    newNumber.EmployeeID = thisEmployee.EmployeeID;
    int highestKey = _fDBC.EmployeePhoneNumbers          //  This is the only difference between these two Handlers,  
                                                         //  Phone Numbers use a non-automated multi-part Key
                          .Where(a => a.EmployeeID == thisEmployee.EmployeeID)
                          .Select(a => a.EmployeePhoneNumberID)
                          .DefaultIfEmpty(-1)                       // Default if set IS EMPTY
                          .Max();

    newNumber.EmployeePhoneNumberID = highestKey + 1;

    try
    {
        _fDBC.EmployeePhoneNumbers.Add(newNumber);

        // INITIALIZING the Validation Checklist here
    }
    catch (DuplicateKeyException ex)
    {
         //  Not getting any exceptions
    }

    bs_EmployeePhoneNumbers.MoveLast();       //  This works fine for the new PhoneNumber
                                              //  The binding source sees the new record and moves to it,
                                              //  the new record is displayed on the Form.
    thisNumber = newNumber;
}

Этот коддобавляет новый номер телефона в контекст, перемещается к нему, и по возвращении новая (пустая) запись отображается в форме, готовой для заполнения.

Теперь странность

Позиция:

private void btn_NewPosition_Click(object sender, EventArgs e)
{
    if (thisPosition != null)
    {
        DbEntityEntry entry = _fDBC.Entry(thisPosition);

        if (entry.State == EntityState.Modified)
        {
                 // PROMPT to save or cancel current, modified record.
        }
    }

    EmployeePosition newPos = new EmployeePosition();
    newPos.EmployeeID = thisEmployee.EmployeeID;               
    newPos.StartDate = DateTime.Today;

    try
    {
        _fDBC.EmployeePositions.Add(newPos);

        // INITIALIZING the Validation checklist here

    }
    catch (DuplicateKeyException ex)
    {
           //  Not getting any exceptions
    }

    bs_EmployeePos.MoveLast();       //  This Code does NOT work. 
                                     //  The bindingsource does NOT see the new record, the move has no effect, 
                                     //  and the current (existing) record is displayed on the form.
    thisPosition = newPos;

}

Этот код создает новую запись, это можно увидеть в отладчике.Bindingsource просто не видит его.

Вопрос в том, «Почему один работает, а другой нет?»

Опять же, единственное различие между этими обработчиками - это запрос LINQ в телефоне.Числовой обработчик для поиска значения субиндекса для новой записи.Этот запрос происходит (очевидно) до инструкции ADD.

Я могу обойти эту проблему, переопределив источник данных Position Bindingsource непосредственно перед перемещением:

bs_EmployeePos.DataSource = thisEmployee.EmployeePositions.Where(ep => ep.EndDate == null).ToList();

Но это вызывает другие проблемы - мешает успешной работе моего обработчика кнопки [Отмена].

Есть идеи?

Спасибо.Росс

Дополнение: определение EmployeePhoneNumber & EmployeePosition:

public partial class EmployeePosition
{
    public int EmployeePositionID { get; set; }

    public int PositionID { get; set; }

    public int EmployeeID { get; set; }

    [Column(TypeName = "date")]
    public DateTime StartDate { get; set; }

    public int PayrollClassID { get; set; }

    public int? InterviewerID { get; set; }

    public int? AssignedWorkstationID { get; set; }

    [Column(TypeName = "date")]
    public DateTime? EndDate { get; set; }

    public decimal FTE { get; set; }

    [Column(TypeName = "tinyint")]
    public Byte? EmployeeRCD { get; set; }                  //  ADD 

    public virtual WorkStation WorkStation { get; set; }

    public virtual Employee Employee { get; set; }

    public virtual PayrollClass PayrollClass { get; set; }

    public virtual Position Position { get; set; }
}


public partial class EmployeePhoneNumber
{
    [Key]
    [Column(Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int EmployeeID { get; set; }

    [Key]
    [Column(Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int EmployeePhoneNumberID { get; set; }

    public int PhoneNumberTypeID { get; set; }

    [Required]
    [StringLength(3)]
    public string AreaCode { get; set; }

    [Required]
    [StringLength(8)]
    public string PhoneNumber { get; set; }

    [StringLength(7)]
    public string PhoneExtention { get; set; }

    [StringLength(25)]
    public string PhoneNumberNote { get; set; }

    public virtual Employee Employee { get; set; }

    public virtual LU_PhoneNumberTypes LU_PhoneNumberTypes { get; set; }
}
...