Use ValueType as identifier

51 views
Skip to first unread message

marcus

unread,
Jul 23, 2014, 5:15:59 AM7/23/14
to rav...@googlegroups.com
I'm trying to use a custom object as an identifier in RavenDB but I can't figure out how to do a proper conversion that includes the tag prefix when converting to and from

My ValueType has two properties like below

public string Id{get;set;}
[JsonIgnore]
public string DraftId{
 get {
 
return this.Id + "/draft";
 
}
}

I want my converter to set the standard Id including the tag prefix, for example pages/34. With the code below the DocumentReference.Id of a loaded document is only 34 and not pages/34 but it stores correctly in the database.
I guess the problem is in the ConvertTo method where I think I need to get hold of the tag prefix? Is that possible?

public class DocumentReferenceTypeConverter : ITypeConverter {
 public bool CanConvertFrom(Type sourceType)
 {
  return sourceType == typeof(DocumentReference);
 }

 public string ConvertFrom(string tag, object value, bool allowNull)
 {
 var identifier = (DocumentReference)value;

 if (string.IsNullOrEmpty(identifier.Id) && allowNull)
 {
  return null;
 }

  return string.Concat(tag, identifier.ToString());
 }

 public object ConvertTo(string value)
 {
  return new DocumentReference(value);
 }
}


Oren Eini (Ayende Rahien)

unread,
Jul 23, 2014, 5:30:19 AM7/23/14
to ravendb
Can you create a failing test? I don't think that I follow the problem.



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.

marcus

unread,
Jul 23, 2014, 5:35:07 AM7/23/14
to rav...@googlegroups.com
I can't say that it's wrong but in my ConvertTo method the value is 1 and does not include the type name/prefix

Oren Eini (Ayende Rahien)

unread,
Jul 23, 2014, 5:36:47 AM7/23/14
to ravendb
Yes, this is tripped for you before hand by the FindIdValuePartForValueTypeConversion convention

marcus

unread,
Jul 23, 2014, 5:40:22 AM7/23/14
to rav...@googlegroups.com
Ok, so I can't convert it to type/n here then?

Oren Eini (Ayende Rahien)

unread,
Jul 23, 2014, 6:20:00 AM7/23/14
to ravendb
You can override the convention.

marcus

unread,
Jul 23, 2014, 8:01:10 AM7/23/14
to rav...@googlegroups.com
I don't understand what you mean, can you give me an example?

marcus

unread,
Jul 23, 2014, 11:19:06 AM7/23/14
to rav...@googlegroups.com

Oren Eini (Ayende Rahien)

unread,
Jul 24, 2014, 3:11:30 AM7/24/14
to ravendb
You want to use the full string in your custom identifier.
We strip that string in here:

DocumentConventions.FindIdValuePartForValueTypeConversion = (entity, id) => id.Split(new[] { IdentityPartsSeparator }, StringSplitOptions.RemoveEmptyEntries).Last();

You can override by setting this property to something else.



Oren Eini

CEO


Mobile: + 972-52-548-6969

Office:  + 972-4-622-7811

Fax:      + 972-153-4622-7811





On Wed, Jul 23, 2014 at 6:19 PM, marcus <mar...@meridium.se> wrote:

marcus

unread,
Jul 24, 2014, 4:20:09 AM7/24/14
to rav...@googlegroups.com
Ah cool, that did the trick.

Are there any drawbacks of using a ValueType as an id?

Oren Eini (Ayende Rahien)

unread,
Jul 24, 2014, 4:26:31 AM7/24/14
to ravendb
Yes, basically, your client side & server side models are now different.
On the server side, this is a string, always. And you get into interesting issues in indexing / transformers / queries if you are working with the id in that manner.

marcus

unread,
Jul 24, 2014, 5:10:08 AM7/24/14
to rav...@googlegroups.com
Even though I convert and use the same id as the server? myObject.Id is "pages/1" on the server and on the client, the only difference is that I use a struct instead of a string on my object. 

Oren Eini (Ayende Rahien)

unread,
Jul 24, 2014, 5:16:16 AM7/24/14
to ravendb
If you are trying to use a property of the object, like: Id.DraftId, it will exist client side, but not server side.

marcus

unread,
Jul 24, 2014, 6:13:26 AM7/24/14
to rav...@googlegroups.com
Ah, I understand the problem and it's kinda ugly to have a reference to a document that does not exist. What is the cleanest way to set the DraftId if the document exists? Do I need a roundtrip to the server or is it possible to to this when the document is loaded?

Oren Eini (Ayende Rahien)

unread,
Jul 24, 2014, 6:23:57 AM7/24/14
to ravendb
I don't understand the question.
The issue is if you do something like this:

session.Query<Item>().Where(x=>x.Id.DraftId == "foo").ToList();

That won't work server side.

marcus

unread,
Jul 24, 2014, 6:26:35 AM7/24/14
to rav...@googlegroups.com
I see what you mean... that might be a bad design decision then. Thanks for you help and feedback

Kijana Woodard

unread,
Jul 24, 2014, 10:39:34 AM7/24/14
to rav...@googlegroups.com
I assume you're doing value type identifiers for an additional layer of compile time assurance?

I sympathize, but I'll say that every time I've gone down that road, it seems to not be worth the effort. I occasionally catch barId being equated to fooId bugs, but it's pretty rare and tests and variable naming go a long way to sorting those out as well.

At any rate, one technique you could use is to set your value type id as another property and then have the Id be a read-only calculation.

pseudo:
class Foo
   Foo(ValueType id){ FooId = id; }
   ValueType FooId {get; private set; }
   string Id { get { return ConvertToRavenId(FooId); } } //use method, ToString, implicit conversion, whatever

If you find yourself with a value type id needing to find a document in the db, add a static method to the document class that does the conversion and have the Id property rely on that as well.


Reply all
Reply to author
Forward
0 new messages