André Reichelt
André Reichelt

Reputation: 1631

Access database context from Entity Framework model class

Usually, I create new database entites with dbContext.MyClass.Create(). In my current application, I need to create such an entity from within an extension method of another model class.

I have the two classes DataEntry and WorkSchedule, where one DataEntry can contain multiple WorkSchedules. Therefore, I added a method DataEntry.FillOrUpdateFromWCF(), which calls a web service and updates some fields. So far, so good.

This method also needs to create new WorkSchedules for this same DataEntry in some cases. The problem is, that I, as far as I know, have no reference to the current DataEntry's database context. Sure, I could just create them with new WorkSchedule(), but that would not update them after saving, right?

So is there something like a this.ThisEntitysDatabaseContext.WorkSchedule.Create() method from within the DataEntry class?

public partial class DataEntry {
  public async Task FillOrUpdate() {
    WcfData[] data = GetSomeDataFromWCF();

    foreach(WcfData wd in data) {
      WorkSchedule ws = this.PathToContext.WorkSchedule.Create();
      ws.Stuff = "test";
      this.WorkSchedules.Add(ws);
    }
  }
}

Upvotes: 1

Views: 1260

Answers (2)

Harald Coppoolse
Harald Coppoolse

Reputation: 30464

Actually, you don't need to ask the DbContext to Create a DataEntry for you. In fact, this is quite uncommon.

Usually you create the object using new, then fill all the properties, except the primary keys and Add the object to the dbContext

using (var dbContext = new MyDbContext())
{

     DataEntry entryToAdd = new DataEntry()
     {
          // fill the properties you want, leave the primary key zero (default value)
          Name = ...
          Date = ...

          WorkShedules = ...
     };

     // add the DataEntry to the database and save the changes
     dbContext.Add(entryToAdd);
     dbContext.SaveChanges();
}

For the WorkSchedules you can use your own function, but you can also assign a value using operator new:

WorkSchedules = new List<WorkSchedule>()
{
    new WorkSchedule() {Name = "...", ...},
    new WorkSchedule() {Name = "...", ...},
    new WorkSchedule() {Name = "...", ...},
},

Note: do not fill the primary key of the work schedule, nor the foreign key of the DataEntry that this Workschedule belongs to, after all, you don't know the value yet.

Entity framework is smart enough to understand the one-to-many relationship, and will add the proper items to the database, with the proper values for the foreign keys.

Upvotes: 1

CodeCaster
CodeCaster

Reputation: 151604

Sure, I could just create them with new WorkSchedule(), but that would not update them after saving, right?

It would, as long as you attach them to a tracked entity. You really don't want access to the DbContext in an entity class, that's an antipattern. You also should reconsider whether you want your entity classes to contain any logic, but that's up for debate.

So if you have something like this:

public class DataEntry
{
    public ICollection<WorkSchedule> Schedules { get; set; }

    public void DoWork()
    {
        Schedules.Add(new WorkSchedule
        {
            Start = DateTime.Now
        });
    }
}

Then this will add the proper record and foreign key (assuming that's all set up properly):

using (var db = new YourContext())
{
    var dataEntry = db.DataEntries.Single(d => d.Id == 42);

    dataEntry.DoWork();

    db.SaveChanges();
}

Upvotes: 2

Related Questions