Search code examples
entity-frameworkasynchronousentity-framework-coreentitydbcontext

Recursive attaching in Entity Framework


Let's assume I have two entities, Folder and File and this is their simplified structure:

File
    public virtual Folder ParentFolder

Folder
    public virtual List<File> Files

Now imagine the user is asynchronously and rapidly creating multiple files, folders, etc., of course I solved this with creating a new DbContext for every operation, so for example when the user creates a folder, I do the following:

var file = new File (fileModel);
var folder = context.Attach (GetFromInMemoryCacheById (fileModel.FolderId));
file.ParentFolder = folder;
folder.Files.Add (file);
context.SaveChanges ();

and soon I get into a problem where whenever I attach the existing folder, all its children often get attached in Added state. So since I get duplicate key added exceptions, I am forced to additionally do something like this so they get Unchanged state:

folder.Files.ForEach (file => context.Attach (File));

But now image my structure is a bit bigger and I have another layer, for example Disk. Suddenly, for even the simplest save action I have to run through a lot of entities to make them be in Unchanged state and this really got out of control really fast.

What would be appropriate way for making DbContext care only about File and its parent Folder, but completely ignore the list of Files it has so I would not have to fix their states all the time?


Solution

  • Didn't want to mess up with ids or set anything to null that shouldn't be null so I ended up setting [NotMapped] on public virtual List<File> Files. I sacrifised the comfort of this property getting set when loading Folder from database (I have to do it manually, but load operation is very infrequent, mostly I care about continuous saving), but now the unexpected entities no longer get into the scope. Hopefully this approach is helpful to others dealing with asynchronous saving in EF.