Problem with immutable types

133 views
Skip to first unread message

Robert Pickering

unread,
Aug 25, 2011, 7:19:24 AM8/25/11
to rav...@googlegroups.com
I using raven db with F#'s immutable record types. Most things work
fine but I've hit a problem when I load a record modify, by creating a
copy, and then try to resave it I get NonUniqueObjectException. This
is because the old unchanged version is still cached in the documents
session. It's fairly easy to work round this is by calling
session.Advanced.Evict with the original object but it would be nice
not to have to do this. I have had a quick look at the code from the
document session and it seems the problem comes from tracking the
objects in the "entitesById" dictionary, would it be possible to
create a mode were entities weren't tracked?

Repo, along with the exception at the bottom of the mail.

Cheers,
Rob

open Raven.Client
open Raven.Client.Document

type MyRecord =
{ mutable Id: string
MyField: string }

let populate() =
let x = { Id = null; MyField = "A test" }
use store = new DocumentStore(Url = "http://localhost:8080")
store.Initialize() |> ignore
use session = store.OpenSession()
session.Store(x)
session.SaveChanges()

//populate()


let main() =
use store = new DocumentStore(Url = "http://localhost:8080")
store.Initialize() |> ignore
use session = store.OpenSession()
let x = session.Load<MyRecord>("myrecords/1")
let x' = { x with MyField = "another test" }
session.Store(x')
session.SaveChanges()

main()

Unhandled Exception: Raven.Client.Exceptions.NonUniqueObjectException: Attempted
to associated a different object with id 'myrecords/1'.
at Raven.Client.Document.InMemoryDocumentSessionOperations.Store(Object entit
y) in c:\Builds\raven\Raven.Client.Lightweight\Document\InMemoryDocumentSessionO
perations.cs:line 529
at Program.main() in c:\code\TestImmutableDocStorage\TestImmutableDocStorage\
Program.fs:line 25
at <StartupCode$TestImmutableDocStorage>.$Program.main@() in c:\code\TestImmu
tableDocStorage\TestImmutableDocStorage\Program.fs:line 28

Ayende Rahien

unread,
Aug 25, 2011, 7:29:54 AM8/25/11
to rav...@googlegroups.com
Robert,
The problem is that this then violate one of the foundations of using the session, the notion of unit of work.
It is a very bad usage of the API if you are using C#.
It is a common case (and perfectly valid) if you are using F#.

I am very hesitant to add something like that to the main code base, but I opened up an extension point (available on the next build) which will allow you to do so:

public class DocumentSessionWithoutUniquing : DocumentSession 
{
  protected override void AssertNoNonUniqueInstance(object entity, string id)
  {
     // we are explicitly not checking that
  }
}

Then you just replace the call to documentStore.OpenSession() with an extension method to open one without tracking.

Robert Pickering

unread,
Aug 25, 2011, 7:51:23 AM8/25/11
to rav...@googlegroups.com
Cool, thanks, looking forward to the next build!
Reply all
Reply to author
Forward
0 new messages