1

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);
    }
  }
}

2 Answers 2

2

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();
}
Sign up to request clarification or add additional context in comments.

1 Comment

Can you please explain, what the disadvantages of putting logic to the entity classes are? From my understanding, the best place for a method to manipulate a DataEntry would be the DataEntry class itself. Or do I oversee something?
1

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.

3 Comments

I once read, that Entity Framework won't track changes done by triggers or default column values when creating an entity with new. The suggestion there was to always use the context's Create() methods.
I never used Create, and my objects are still created. Simply write a unit test to see which method works best.
I've tested it, and it doesn't work. I've created a new entity with new, added it to a table, and after SaveChanges, all the navigation properties are still null.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.