Cloning a Document

703 views
Skip to first unread message

Mark

unread,
Apr 4, 2012, 9:32:35 AM4/4/12
to ravendb
Hi,

We are attempting to do "save as", effectively copying the document
but giving it a new specific id.
We are trying to do this via:

var doc = session.Advanced.DatabaseCommands.Get("docid")

doc.Key= "docid2"

session.Store(doc, "docid2")

However this fails.

How best should we go about copying a document, metadata and all to a
"new" document?

Thanks


Oren Eini (Ayende Rahien)

unread,
Apr 4, 2012, 9:34:09 AM4/4/12
to rav...@googlegroups.com
var foo = session.Load<Foo>("foos/1");
session.Advanced.Evict(foo);
session.Store(foo,"foo/2");
session.SaveChanges();

Mark

unread,
Apr 4, 2012, 9:43:53 AM4/4/12
to ravendb
Thanks!

What assembly is Evict in? As I am getting undefined function for
ISyncAdvancedSessionOperation.

Also does this leave the original document in the project?

On Apr 4, 2:34 pm, "Oren Eini (Ayende Rahien)" <aye...@ayende.com>
wrote:

Mark

unread,
Apr 4, 2012, 9:56:35 AM4/4/12
to ravendb
This is exactly what we are doing, build 700:

var doc = session.Load<dynamic>(oldLayoutId);
session.Advanced.Evict<dynamic>(doc); // <---- Cannot find Evict
method, with or without the <dynamic>
session.Store(doc, newLayoutId);
session.SaveChanges();

Oren Eini (Ayende Rahien)

unread,
Apr 4, 2012, 10:05:00 AM4/4/12
to rav...@googlegroups.com
It is in Raven.Client.Lightweight

The method is defined on IAdvancedDocumentSessionOperations

Mark

unread,
Apr 4, 2012, 10:09:42 AM4/4/12
to ravendb
Hmm,

We are referencing that dll.

We hare using IDocumentSession that has a
ISyncAdvancedSessionOperation type for the Advanced property. Is this
why it is going wrong?

Thanks

On Apr 4, 3:05 pm, "Oren Eini (Ayende Rahien)" <aye...@ayende.com>

Oren Eini (Ayende Rahien)

unread,
Apr 4, 2012, 10:10:33 AM4/4/12
to rav...@googlegroups.com
No, 
IAdvancedDocumentSessionOperations  is the parent of  ISyncAdvancedSessionOperation  

Chris Marisic

unread,
Apr 4, 2012, 10:13:34 AM4/4/12
to rav...@googlegroups.com
ISyncAdvancedSessionOperation : IAdvancedDocumentSessionOperations

Assuming you have the  Raven.Client.Lightweight.dll referenced I'm not sure how you could get a build error there as these are direct implementations

Mark

unread,
Apr 4, 2012, 10:14:28 AM4/4/12
to ravendb
It's not a build error but a runtime error which is why it has me a
bit confused.

Perhaps because our object type is dynamic?

Oren Eini (Ayende Rahien)

unread,
Apr 4, 2012, 10:17:31 AM4/4/12
to rav...@googlegroups.com
What runtime errors?
What is the code? What is the error?

Mark

unread,
Apr 4, 2012, 10:18:14 AM4/4/12
to ravendb
Actual exception is as follows:

------------
A first chance exception of type
'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occured in
Microsoft.CSharp.dll

Additional information: 'Raven.Client.ISyncAdvancedSessionOperation'
does not contain a definition for 'Evict'
-------------

Thanks

Oren Eini (Ayende Rahien)

unread,
Apr 4, 2012, 10:21:01 AM4/4/12
to rav...@googlegroups.com
No idea, and it most certainly should work.
Cast the value to object, and try again.
Maybe it can't handle interface inheritence?

Mark

unread,
Apr 4, 2012, 10:29:15 AM4/4/12
to ravendb
If I change it to the following, it finds Evict but then fails to
save...

try
{
var doc = (object)session.Load<dynamic>(oldLayoutId);
session.Advanced.Evict<object>(doc);
session.Store(doc, newLayoutId);
session.SaveChanges();
}
catch (Exception ex)
{
var s = ex.ToString();
throw ex;
}

our objects are dynamic, so maybe we should use IDynamicJsonObject or
whatever for this???

Call stack/exception now is
Raven.Client.Exceptions.NonUniqueObjectException: Attempted to
associated a different object with id 'Layouts/RadioListLayout.v2'.
at
Raven.Client.Document.InMemoryDocumentSessionOperations.AssertNoNonUniqueInstance(Object
entity, String id) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight
\Document\InMemoryDocumentSessionOperations.cs:line 608
at
Raven.Client.Document.InMemoryDocumentSessionOperations.StoreInternal(Object
entity, Nullable`1 etag, String id) in c:\Builds\RavenDB-Stable
\Raven.Client.Lightweight\Document
\InMemoryDocumentSessionOperations.cs:line 584
at
Raven.Client.Document.InMemoryDocumentSessionOperations.Store(Object
entity, String id) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight
\Document\InMemoryDocumentSessionOperations.cs:line 532
[our calling code]



On Apr 4, 3:21 pm, "Oren Eini (Ayende Rahien)" <aye...@ayende.com>

Oren Eini (Ayende Rahien)

unread,
Apr 4, 2012, 10:30:45 AM4/4/12
to rav...@googlegroups.com
       var doc = session.Load< object >(oldLayoutId);

And you also need to make sure that the doc id is set to the right value.

Mark

unread,
Apr 4, 2012, 10:45:00 AM4/4/12
to ravendb
I've tried this:

var doc = (object)session.Load<object>(oldLayoutId);
session.Advanced.Evict<object>(doc);

((IDynamicJsonObject) doc).Inner["Id"] = newLayoutId;

session.Store(doc, newLayoutId);
session.SaveChanges();

Which is setting the document element Id to the new id, however how do
we get to the raven doc id? What should we cast it to?

Also on a side note, having periods '.' in the document name shouldn't
cause any problems right?

Thanks

On Apr 4, 3:30 pm, "Oren Eini (Ayende Rahien)" <aye...@ayende.com>

Oren Eini (Ayende Rahien)

unread,
Apr 4, 2012, 10:47:15 AM4/4/12
to rav...@googlegroups.com
Can you create a failing test?

Mark

unread,
Apr 4, 2012, 11:08:33 AM4/4/12
to ravendb
Yeah, it's very simple,


var oldLayoutId = "Layout/Doc1";
var newLayoutId = "Layout/Doc1.v2"; // we know about the revision
module but this is for a different semantic usage

var doc = (object)session.Load<object>(oldLayoutId);

// stop tracking changes, allows "save as" on store.
session.Advanced.Evict(doc);

// update the doc id field, but is this ravens? Not even sure if this
will clone the metadata, as doc doesn't seem to contain it...
((IDynamicJsonObject) doc).Inner["Id"] = newLayoutId;

session.Store(doc, newLayoutId);
session.SaveChanges();

The document can be any valid json; we don't have a class structure to
match against it so use the "dynamic" usually. Note at the root of the
document we have an "Id" field.

so for example:

{
"skin": "",
"scripts": [ ],
"layoutdocument": { },
"Id": "Layouts/Doc1"
}

Basically we want to copy the documents content *and* metadata to a
new document, leaving the old one alone. Is there a simple work around
to do this?

Thanks

On Apr 4, 3:47 pm, "Oren Eini (Ayende Rahien)" <aye...@ayende.com>

Oren Eini (Ayende Rahien)

unread,
Apr 4, 2012, 2:02:28 PM4/4/12
to rav...@googlegroups.com
This isn't a valid test case, for test cases, see the Raven.Tests project in the ravendb source code.

marcus

unread,
Aug 6, 2014, 1:09:04 PM8/6/14
to rav...@googlegroups.com
What happened with this issue? I'm experiencing the same problem when I'm using a dynamic.

Oren Eini (Ayende Rahien)

unread,
Aug 6, 2014, 1:10:04 PM8/6/14
to ravendb
I have no idea what this issue is, this thread is 2 years old. Please create a new one with the background information.



Oren Eini

CEO


Mobile: + 972-52-548-6969

Office:  + 972-4-622-7811

Fax:      + 972-153-4622-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+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Chris Marisic

unread,
Aug 6, 2014, 2:39:41 PM8/6/14
to rav...@googlegroups.com
Useful information for this thread. The supplied methods in this thread don't truly clone your document. If your document is Cat, it's effectively new Cat(). If the document had any important metadata that needed cloned that would be lost.

If you want to truly clone the documents with the metadata and all, you need to copy the metadata over to the new representation.
Reply all
Reply to author
Forward
0 new messages