I am trying to build a Patient's edit form that will get Patient data from a database using EF Core and the DbContext derived AppDbContext.

On the same form there will be a dropdown combobox that will be displaying all the available insurances (fetched from the database).

What I want to achieve is the ability, the user to be able to select an existing insurance (which is obvious and easily achieved) or to add a new one by typing it into the combobox and this new entry should be selected as the patient's insurance from now on until the SaveChanges takes place and when the same patient is reopened for editing.

I use two BindingSources one for the patient itself (bsPatient) and one for the insurances list (bsInsurances).

I have the following two models (1:many relationship)

public class Insurance
{
    public int Id { get; set; }
    public string Name { get; set; } = String.Empty;

    public virtual ObservableCollectionListSource<Person> Persons { get; } = new();
}

public class Person
{
    public int Id { get; set; }
    public string LastName { get; set; } = String.Empty;
    public string FirstName { get; set; } = String.Empty;
    public DateTime DOB { get; set; }
   
    public int InsuranceId { get; set; }
    public Insurance Insurance { get; set; } = null;
}

And this is the DbContext:

public class AppDbContext : DbContext
{
    private const string DatabaseFileName = "MyPatientsDB.sqlite3";

    public DbSet<Person> Persons { get; set; }
    public DbSet<Insurance> Insurances { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder
        .UseSqlite(@$"Data Source={DatabaseFileName}");

On the form there will be

public partial class PatientForm : Form
{
    private AppDbContext _db = new();
    private int _patientId = 0;
    ObservableCollection<Insurance> _insurancesList = new();

    public PatientForm(int patientId)
    {
        InitializeComponent();

        _patientId = patientId;
    }

    protected async override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        await _db.Insurances.LoadAsync();
        _insurancesList = new ObservableCollection<Insurance>(_db.Insurances.Local);
        bsInsurances.DataSource = _insurancesList;

        bsPatient.DataSource = await _db.Persons.FirstOrDefaultAsync(p => p.Id == _patientId);
    }

    protected async override void OnFormClosing(FormClosingEventArgs e)
    {
        base.OnFormClosing(e);

        bsInsurances.EndEdit();

        if (cbInsurances.FindStringExact(cbInsurances.Text) == -1)
        {
            var newInsurance = new Insurance { Id = 0, Name = cbInsurances.Text };
            _db.Insurances.Local.Add(newInsurance);
        }
        
        bsPatient.EndEdit();

        await _db.SaveChangesAsync();

        _db?.Dispose();
    }
}

So far, I am able to save correctly the Insurance selection of the combobox when an already existing item is selected. The problem arises when the user inserts a new insurance entry into the combo textbox. This new entry can not be saved to the db and be displayed the next time the same patient is opened for editing.

I would be grateful if someone could point me towards which direction to follow to achieve this. I mean, while editing a patient's data how to be able to insert a new entry into the insurances combo and this new entry to be persisted into the db and be displayed and selected the next time the patient is opened for editing.

1

There are 1 best solutions below

0
NAngelGr On

I think I've found a solution. I don't know if it is the best one but it seems to be working at least into my project. I am just referring it in case someone else has the same query. Please if anyone has a better solution I would be grateful for his/her help.

    protected async override void OnFormClosing(FormClosingEventArgs e)
    {
        base.OnFormClosing(e);

        bsInsurances.EndEdit();

        if (cbInsurances.FindStringExact(cbInsurances.Text) == -1)
        {
            if (bsPatient != null && bsPatient.DataSource != null)
            {
                (bsPatient.DataSource as Person).Insurance = new Insurance() { Name = cbInsurances.Text as string };
            }
        }

        bsPatient.EndEdit();

        await _db.SaveChangesAsync();

        _db?.Dispose();
    }