Ответ 1
Проблема
Здесь сделка, если у вас есть свойство dynamic
, тогда RavenDB будет всегда десериализовать его как RavenJObject
. Например:
public class User {
public dynamic Data = new ExpandoObject();
}
...
var user = new User();
user.Data.SomethingNew1 = "foo";
Это выглядит безобидно и прекрасно работает при создании вашего пользователя. Но когда вы Загрузить пользователь, RavenDB не знает, какой тип вы хотите для dynamic
, поэтому он использует RavenJObject
. Вы не можете динамически создавать свойства (expando style) с помощью RavenJObject
, чтобы это не удалось:
var user = session.Find<User>(...);
user.Data.SomethingNew2 = "foo"; //compiles, but throws
Мое решение
Используйте ExpandoObject
и явно определите его тип в сериализованном свойстве. Это позволяет RavenDB (или JSON, я думаю) знать, какого типа вы ожидаете, и ему не нужно угадывать RavenJObject
. Затем, чтобы сохранить синтаксическую магию, оберните свойство динамическим аксессуаром.
public class User {
public ExpandoObject _Data = new ExpandoObject();
public dynamic Data {
get { return _Data; }
}
}
Есть способы сделать объект expando частным и создать сеттер для Data
, но вы получите эту идею.
Дополнительные проблемы
Обновление: К сожалению, это решение предоставляет больше проблем. Скажем, вы сохраняете список строк в динамических данных:
user.Data.Keys = new List<String>{"a","b","c"};
После сериализации/десериализации JSON/Raven снова не знает, какого типа вы ожидаете. Поэтому, если вы попробуете это (см. Ниже), тогда он компилируется, но вы получаете исключение во время выполнения. Невозможно неявно преобразовать тип "Raven.Abstractions.Linq.DynamicList" в "System.Collections.Generic.List":
List<string> keys = user.Data.Keys;