Raven Clr Type causes "Could not convert document {raven-clr-type} to entity of type {another-type}"

643 views
Skip to first unread message

Jeff Pang

unread,
Oct 22, 2014, 11:35:19 PM10/22/14
to rav...@googlegroups.com
When there are 2 or more POCO classes with similar schema, querying the document across the different entities may cause "Could not convert document {raven-clr-type} to entity of type {another-type}" error when the metadata Raven-Clr-Type is present, but when Raven-Clr-Type is deleted, the conversion is possible.

Consider the following:

namespace Project1
{
   
public class Class1
   
{
       
public string SomeProperty { get; set; }
       
public bool ShouldLoad { get; set; }
   
}
}
namespace Project2
{
   
public class Class1
   
{
       
public string SomeProperty { get; set; }
       
public bool ShouldLoad { get; set; }
   
}
}

Usage:

var p2c1 = from c in session.Query<Class1>() where c.ShouldLoad select c;

If metadata Raven-Clr-Type for the document is "Project1.Class1, Some.Location" the query will fail with "Could not convert document Project1.Class1 to entity of type Project2.Class1", but If i delete the Raven-Clr-Type the query works correctly.

My question is then
1. What is the purpose of having Clr-type since it can still parse the entity correctly without it.
2. Isn't RavenDB suppose to be schema-less? This "feature" seems contrary to principle.
3. How do I fetch the document without relying on the DatabaseCommands.Get(id) method because the method fetch only a single document by Id and doesn't let me query with conditions.
4. Is there a way to save documents without including the Raven-Clr-Type metadata


Oren Eini (Ayende Rahien)

unread,
Oct 23, 2014, 4:57:12 AM10/23/14
to ravendb
That is by design. 

1) You need this to be able to handle session.Load<Animal>("dogs/1"); and get the right instance.
2) Yes, it is schema less, but note that you code explicitly want to use a schema, by supply a type. If you want it to be schemaless, ask for a dynamic, and it will work.
3) I don't understand the question. Do you want to query? Session.Query<T> is there for that.
4) You can use a document store listener to remove it, but you'll need to explain first why you are trying to access those things in such a strange fashion.


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

Kijana Woodard

unread,
Oct 23, 2014, 11:16:40 AM10/23/14
to rav...@googlegroups.com
IIRC, if "Project1.Class1" is the Raven-Clr-Type, but "Project1.Class1" isn't reference in the assembly, Loading "Project2.Class1" will work. In other words, if these are actually disconnected projects, you would get the benefit you are looking for.

Kijana Woodard

unread,
Oct 23, 2014, 11:18:22 AM10/23/14
to rav...@googlegroups.com

Jeff Pang

unread,
Oct 27, 2014, 6:44:52 AM10/27/14
to rav...@googlegroups.com
1) But I am able to still handle session.Load<Animal>("dogs/1") even without the Clr-Type as long as the json schema matches the POCO
2 & 4) I have multiple projects querying from the same document, but they may not share the same class definition as they are separate .Net projects with different namespaces, although the POCO's schema is similar enough to serialise/deserialise from poco.
3) Yes i would like to use session.Query<Project1.Class1>() where ... inside a project, and then session.Query<Project2.Class1>() where  ... in another project. Both share the same document in RavenDB, but if the document has a "Clr-Type" defined, one or the other query will fail.

Jeff Pang

unread,
Oct 27, 2014, 6:49:54 AM10/27/14
to rav...@googlegroups.com
The exact scenario in my case is that we are working on multiple projects by different developers, and the projects don't necessary share a single dll whereby all the POCOs are defined, but they share the same Json data in ravendb. So when a project creates a document, it must be able be read/written by another .Net project without direct reference to each other's classes, as long as the schema of the POCO matches the Json in RavenDb.

Oren Eini (Ayende Rahien)

unread,
Oct 27, 2014, 10:34:02 AM10/27/14
to ravendb
1) Not really, you won't be able to access any property of Dog from there.
2 & 4) Similar doesn't mean identical. When you have a property on one class that isn't on the other, what do you expect to happen?
3) Then you need to strip the clr type, and accept the consequences.

Oren Eini (Ayende Rahien)

unread,
Oct 27, 2014, 10:34:24 AM10/27/14
to ravendb
That is a VERY bad idea, mind.

Kijana Woodard

unread,
Oct 27, 2014, 11:06:20 AM10/27/14
to rav...@googlegroups.com
You're saying that scenario doesn't work?
I was actually quite surprised/happy that it did work when preparing a talk on raven earlier this year.

From: Jeff Pang
Sent: ‎10/‎27/‎2014 5:49 AM
To: rav...@googlegroups.com
Subject: Re: [RavenDB] Raven Clr Type causes "Could not convert document{raven-clr-type} to entity of type {another-type}"

Chris Marisic

unread,
Oct 27, 2014, 12:29:59 PM10/27/14
to rav...@googlegroups.com
+1 on this being a bad idea.

Use nuget to share the database models. Just mark everything virtual or you could make the models themselves .cs.pp files to come out as actual code files in the consuming project (the downside to this is marrying changes together across projects)

Kijana Woodard

unread,
Oct 27, 2014, 12:37:18 PM10/27/14
to rav...@googlegroups.com
-0 on this being a bad idea.

It _might_ be  bad idea depending on usage, but it can also be a powerful idea if used with intent. Warnings do apply: running with scissors and all that.

In fact, iirc, there is support in 2.5+ for exactly this approach where "missing document properties" are not thrown away by the client.

That would allow different contexts to work with different aspects of a document and evolve on their own.
That said, the same can be accomplished with Transformers and separate documents. But it's an interesting choice.

Oren Eini (Ayende Rahien)

unread,
Oct 27, 2014, 1:01:47 PM10/27/14
to ravendb
That support is in 3.0, and it is meant for migrations support, more than this issue.
Now, you can make it work by asking RavenDB (via a listener) to erase the CLR type.

Kijana Woodard

unread,
Oct 27, 2014, 1:32:44 PM10/27/14
to rav...@googlegroups.com
I should add that sharing documents across programs might indicate that your modeling is off kilter and you're "integrating through the database".

Jeff Pang

unread,
Oct 27, 2014, 11:11:17 PM10/27/14
to rav...@googlegroups.com
Even if the model is shared via a single DLL, the data will still come from reading directly from database so it is technically that is integrating through the database as well. Besides, it is probably inevitable that programs have to read direct from database at some point.

That being said, my intent wasn't to use the database as some sort of data transport or business logic controller. It is simply a write once read multiple type of data. It will be quite cumbersome to have a service just to centralize that small set of data between the programs.

Jeff Pang

unread,
Oct 27, 2014, 11:20:08 PM10/27/14
to rav...@googlegroups.com
Yeah, it didn't work when I tried just a few days ago. Interesting that you have observed it worked earlier, though I cannot confirm I think I had the same experience too much earlier. Could it be due to some changes in the raven?

Jeff Pang

unread,
Oct 27, 2014, 11:40:22 PM10/27/14
to rav...@googlegroups.com
2 & 4) Consider the following code

class Class1
       
{
           
public string PropA { get; set; }
           
public string PropB { get; set; }
       
}
       
class Class2
       
{
           
public string PropA { get; set; }
           
public string PropC { get; set; }
       
}

Usage:
           
Class1 c1=new Class1(){ PropA="A",PropB="B"};
           
string json=Newtonsoft.Json.JsonConvert.SerializeObject(c1);
           
Class2 c2 = Newtonsoft.Json.JsonConvert.DeserializeObject<Class2>(json);

As far as newtonsoft goes, the missing properties are ignored. Which might be desirable because that allows models to be independent and be catered to the program's specific designs, and thus there will be less requirement for wrappers and adaptors.

3) Yes I understand that. I will need to strip off the clr
Reply all
Reply to author
Forward
0 new messages