DocumentMetadata in OnAfterSaveChanges does not include newly added metadata

79 views
Skip to first unread message

marcus

unread,
Feb 20, 2018, 6:03:42 AM2/20/18
to RavenDB - 2nd generation document database
I use the following code to create and set metadata.

                var about = new About { Heading = $"My heading 2" };
                await session.StoreAsync(about);

                var metadata = session.Advanced.GetMetadataFor(about);
                metadata.Add("Name","FooBar");

                await session.SaveChangesAsync();

Then in the OnAfterSaveChanges I try to access to metadata like this

            store.OnAfterSaveChanges += (object sender, AfterSaveChangesEventArgs args) => {              
                var name = args.DocumentMetadata["Name"];              
            };

But the key does not exist?

Exception has occurred: CLR/System.Collections.Generic.KeyNotFoundException
An exception of type 'System.Collections.Generic.KeyNotFoundException' occurred in Raven.Client.dll but was not handled in user code: 'Name is not in the metadata'
   at Raven.Client.Json.MetadataAsDictionary.get_Item(String key) in C:\Builds\RavenDB-Stable-4.0\src\Raven.Client\Json\MetadataAsDictionary.cs:line 89
   at src.ServiceCollectionExtensions.<>c.<.cctor>b__9_1(Object sender, AfterSaveChangesEventArgs args) in /Users/maqe/temp/aspnet5/src/ServiceCollectionExtensions.cs:line 53
   at Raven.Client.Documents.Session.Operations.BatchOperation.SetResult(BlittableArrayResult result) in C:\Builds\RavenDB-Stable-4.0\src\Raven.Client\Documents\Session\Operations\BatchOperation.cs:line 45
   at Raven.Client.Documents.Session.AsyncDocumentSession.<SaveChangesAsync>d__20.MoveNext() in C:\Builds\RavenDB-Stable-4.0\src\Raven.Client\Documents\Session\AsyncDocumentSession.cs:line 124


Oren Eini (Ayende Rahien)

unread,
Feb 20, 2018, 7:34:51 AM2/20/18
to ravendb

Hibernating Rhinos Ltd  

Oren Eini l CEO Mobile: + 972-52-548-6969

Office: +972-4-622-7811 l Fax: +972-153-4-622-7811

 


--
You received this message because you are subscribed to the Google Groups "RavenDB - 2nd generation document database" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

marcus

unread,
Feb 20, 2018, 7:43:23 AM2/20/18
to RavenDB - 2nd generation document database
Ok, let me know when it's fixed.
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+u...@googlegroups.com.

Oren Eini (Ayende Rahien)

unread,
Feb 20, 2018, 7:50:34 AM2/20/18
to ravendb
Tests are running now :-)
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+unsubscribe@googlegroups.com.

marcus

unread,
Feb 20, 2018, 7:55:02 AM2/20/18
to RavenDB - 2nd generation document database
You are a fast worker :)

marcus

unread,
Feb 20, 2018, 9:30:21 AM2/20/18
to RavenDB - 2nd generation document database
It seems to be an issue with OnBeforeDelete also. When I try to access the DocumentMetadata I get an exception that says that the document does not exist in the current session. If it's OnBeforeDelete I guess it should be accessible?

Den tisdag 20 februari 2018 kl. 13:50:34 UTC+1 skrev Oren Eini:

Oren Eini (Ayende Rahien)

unread,
Feb 20, 2018, 9:41:01 AM2/20/18
to ravendb
No, at that time, the document has already been removed.

To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+unsubscribe@googlegroups.com.

marcus

unread,
Feb 20, 2018, 9:46:15 AM2/20/18
to RavenDB - 2nd generation document database
Hm ok, according to the documentation the document should be removed when SaveChanges is called?

Entities can be marked for deletion by using the Delete method, but will not be removed from the server until SaveChanges is called. koden här...

Oren Eini (Ayende Rahien)

unread,
Feb 21, 2018, 2:00:45 AM2/21/18
to ravendb
Yes, but that is on the server side.
On the session, once you delete an instance, we remove it immediately.
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+unsubscribe@googlegroups.com.

marcus

unread,
Feb 21, 2018, 2:28:55 AM2/21/18
to RavenDB - 2nd generation document database
Ok, I understand. Then I need to take a different approach like this https://groups.google.com/d/msg/ravendb/8aS-EypbQ3o/ulQTUMOWBQAJ

RemoveWhere does not seem to exist. Is it possible to solve this in any other way?

I need to delete an entry from a dictionary based on a criteria that includes the DocumentId.

marcus

unread,
Feb 21, 2018, 3:52:47 AM2/21/18
to RavenDB - 2nd generation document database
I have updated to the latest nightly now and the metadata seems to be included now but the patch I try to do does not get executed?

This is the complete code I try to run:

            store.OnAfterSaveChanges += (object sender, AfterSaveChangesEventArgs args) => {
              if(args.Entity.GetType().GetCustomAttributes(typeof(ViewModelAttribute), false).Any()) {

                var controllerType = args.Entity.GetType().Name;
                var key = args.DocumentMetadata["Url"];
                PatchCommandData patchCommandData = new PatchCommandData($"sites/{requestCultureFeature.RequestCulture.Culture.Name}", null, new PatchRequest
                {
                  Script = "this.Trie[args.Key] = args.TrieNode",
                  Values =
                  {
                      { "TrieNode", new TrieNode(args.DocumentId, controllerType) { Name = controllerType } },
                      { "Key", $"{key}" }
                  }
                }, null);

                ((IAsyncDocumentSession)args.Session).Advanced.Defer(patchCommandData);
              }
            };

With this code nothing seems to get patched?

Oren Eini (Ayende Rahien)

unread,
Feb 21, 2018, 3:55:32 AM2/21/18
to ravendb
I just tested this, and it looks like it is working. 
Can you capture the fiddler output?
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+unsubscribe@googlegroups.com.

marcus

unread,
Feb 21, 2018, 5:34:13 AM2/21/18
to RavenDB - 2nd generation document database
I'm running this code on my mac and fiddler is not available. Have you tried my exact code? The patch executes if I run it in OnBeforeStore but not in OnAfterSaveChanges?

marcus

unread,
Feb 21, 2018, 5:42:32 AM2/21/18
to RavenDB - 2nd generation document database
According to my http debug tool the client does not execute the patch at all?



Den onsdag 21 februari 2018 kl. 09:55:32 UTC+1 skrev Oren Eini:

marcus

unread,
Feb 21, 2018, 5:51:28 AM2/21/18
to RavenDB - 2nd generation document database
This is how the output look if I run the exact same patch in OnBeforeStore instead of OnAfterSaveChanges

Oren Eini (Ayende Rahien)

unread,
Feb 21, 2018, 5:54:40 AM2/21/18
to ravendb
This test is passing:


        [Fact]
        public async Task CanPatchDictionaryUsingArgs()
        {
            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new Item(), "items/first");
                    await session.SaveChangesAsync();
                }
                using (var session = store.OpenAsyncSession())
                {
                    session.Advanced.Defer(new PatchCommandData("items/first", null,
                        new Raven.Client.Documents.Operations.PatchRequest
                        {
                            Script = @"this.Items[args.Key] = args.Value;",
                            Values =
                            {
                                ["Key"] = "A",
                                ["Value"] = "B"
                            }
                        }, null));
                    await session.SaveChangesAsync();
                }

                using (var session = store.OpenAsyncSession())
                {
                    var item = await session.LoadAsync<Item>("items/first");
                    Assert.Equal("B", item.Items["A"]);
                }
            }
        }
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+unsubscribe@googlegroups.com.

marcus

unread,
Feb 21, 2018, 7:24:56 AM2/21/18
to RavenDB - 2nd generation document database
Yes, but can you test to patch when the event OnAfterSaveChanges fires?

Oren Eini (Ayende Rahien)

unread,
Feb 21, 2018, 7:28:59 AM2/21/18
to ravendb
What do you mean, you want to add a patch _on the after save changes_ ?
You would have to call SaveChanges again for it to even work
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+unsubscribe@googlegroups.com.

marcus

unread,
Feb 21, 2018, 7:49:50 AM2/21/18
to RavenDB - 2nd generation document database
Ok, I thought that the patch was executed in a different context but I guess it isn't then.

I guess I'm in need of a different event then. Like OnBeforeSaveChanges. With such event I would have access to the metadata and because it's before savechanges I would be able to create the patch based on the metadata for a specific object.

OnBeforeStore is to early for me because the metadata is not available for new objects and OnAfterSaveChanges is to late because I can not execute the patch.

So as an example I'm creating a new object like this:

using(var session = _documentStore.OpenAsyncSession()) {

                var about = new About { Heading = $"My heading 2" };
                await session.StoreAsync(about);

                var metadata = session.Advanced.GetMetadataFor(about);
                metadata.Add("Url", "/about");

                await session.SaveChangesAsync();

            };

And then I need to patch my Trie object using the metadata for the new about page. Is it possible? If not, does such an event fit into the product?

Oren Eini (Ayende Rahien)

unread,
Feb 21, 2018, 8:38:46 AM2/21/18
to ravendb
OnBeforeStore _has_ metadata available.

 private class Document
        {
            public string Id { get; set; }
        }

        [Fact]
        public void MetadataIsAvailableOnBeforeStoreEvent()
        {
            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenSession())
                {
                    session.Advanced.OnBeforeStore += (sender, args) =>
                    {
                        args.DocumentMetadata["Value"] = "a";
                    };

                    session.Store(new Document
                    {
                        Id = "my-id/123"
                    });

                    session.SaveChanges();
                }

                using (var session = store.OpenSession())
                {
                    var s = session.Load<Document>("my-id/123");
                    Assert.Equal("a", session.Advanced.GetMetadataFor(s)["Value"]);
                }
            }
        }

To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+unsubscribe@googlegroups.com.

marcus

unread,
Feb 21, 2018, 10:16:00 AM2/21/18
to RavenDB - 2nd generation document database
Yes I know but not for new documents. This is what I'm trying to do

        [Fact]
        public void Test()
        {
            using (var documentStore = GetDocumentStore())
            {
                using (var session = documentStore.OpenSession())
                {
                    session.Advanced.OnBeforeStore += (sender, args) =>
                    {
                      // Access the document metadata so I can create a new entry in the Trie using the Patch API
                      var url = args.DocumentMetadata["Url"];
                    };

                    // Create a new document
                    var document = new Document
                    {
                        Id = "my-id/123"
                    };

                    session.Store(document);

                    // Add new metadata to the newly added document
                    var metadata = session.Advanced.GetMetadataFor(document);
                    metadata["Url"] = "/my-url";

                    session.SaveChanges();
                }
            }
        }

Oren Eini (Ayende Rahien)

unread,
Feb 21, 2018, 11:20:47 AM2/21/18
to ravendb
This test works for me.
Note that I'm running with the previous fix, which is likely the reason
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+unsubscribe@googlegroups.com.

marcus

unread,
Feb 21, 2018, 11:40:48 AM2/21/18
to RavenDB - 2nd generation document database
I downloaded the latest build for both the server and client and it worked perfectly. Thanks the fix and your help!
Reply all
Reply to author
Forward
0 new messages