Skip to content
This repository has been archived by the owner on Aug 10, 2024. It is now read-only.

Updating a Child "Document" inside array #23

Closed
samofwise opened this issue Jul 19, 2018 · 2 comments
Closed

Updating a Child "Document" inside array #23

samofwise opened this issue Jul 19, 2018 · 2 comments

Comments

@samofwise
Copy link

I am wondering how I would go about updating an child instance in an array?

Here are my models

public class Recording
{
	[BsonId]
	[Key]
	[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
	public ObjectId Id { get; set; }
		
	//Other Properties

	public List<VideoFragment> VideoFragments { get; set; } = new List<VideoFragment>();
}
[ComplexType]
public class VideoFragment
{
	public string Url { get; set; }
	public byte[] Data { get; set; }
}

Here is my Context

public class MyDbContext : DbContext
{
	public StreamcorderDbContext(DbContextOptions options) : base(options)
	{ }

	public DbSet<Recording> Recordings { get; set; }
}

I am wanting to update an existing Video Fragment by looking it up by Url then saving a byte array of data
Here is what I currently have:

public void SaveFragmentData(ObjectId recordingId, string fragmentUrl, byte[] data)
{
	var recording = _db.Recordings.Single(r => r.Id == recordingId);
	var fragment = recording.VideoFragments.Single(f=> f.Url == fragmentUrl);
	fragment.Data = data;
	_db.Recordings.Update(recording);
	_db.SaveChanges();
}

I add get the recording, update the specific fragment of the recording then save it.

I was hoping there might be a way to just get the fragment and update it individually.

Here is a copy of my document:

{
  "_id": "5b5099d4139c5907ccddeac3",
  "VideoFragments": [
    {
      "Url": "http://video-edge-85675c.syd01.abs.hls.ttvnw.net/v1/segment/CqEDdEsv7E8bCOEbkLIhBFQSmJ8XZv2-_1G....ts",
      "Data": "<Binary Data>"
    },
    {
      "Url": "http://video-edge-85675c.syd01.abs.hls.ttvnw.net/v1/segment/CqED-2SjHzRiHw4Vx9aIaGm8YrO2IVICuhK....ts",
      "Data": "<Binary Data>"
    },
    {
      "Url": "http://video-edge-85675c.syd01.abs.hls.ttvnw.net/v1/segment/CqEDj_wly9Rd0ZviOtA70UkzqGJHAE8jgZA....ts",
      "Data": null
    },
    {
      "Url": "http://video-edge-85675c.syd01.abs.hls.ttvnw.net/v1/segment/CqED5gZajJanx0rSVEt7tWTcr0s_hPBbMML....ts",
      "Data": null
    },
    {
      "Url": "http://video-edge-85675c.syd01.abs.hls.ttvnw.net/v1/segment/CqED4FZm9CfX5NVYVSYGhwbCpzW4nOTObmP....ts",
      "Data": "<Binary Data>"
    }
  ]
}

Could you help me out?

Ps thanks for creating a provider like this, its super helpful to try out.

@crhairr
Copy link
Member

crhairr commented Jul 19, 2018

You're welcome!

Currently, the provider only works on top-level Entities, as these are the only values tracked by the change tracker. This means that entire document has to be saved, which is done with a ReplaceOne call.

The change tracker may not recognize deeply nested documents as a "change" since it doesn't track properties of properties (ie: properties of sub-documents). To get around this, you can mark the Entity as updated by calling DbContext.Update<TEntity>(TEntity entity). This will mark the top-level entity as modified, and the next call to DbContext.SaveChanges() will replace the entire document.

The next version of EFCore recently implemented better support for collections of owned entities, which might make this moot. Depending on well it works, I might be able to break up SaveChanges so that it can push and remove array items. I haven't had time to work on that upgrade, or upgrading the provider to support MongoDB 4.0 ACID transactions. I hope to get some time to do both soon.

@crhairr
Copy link
Member

crhairr commented Dec 19, 2018

The work for this is being done as part of the fix for #33.

@crhairr crhairr closed this as completed Dec 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants