こんにちは、私はこれが古いことを知っていますが、私のように同じ問題を抱えていて、フォーラムで何時間もかけて回答を探している人を助けるために、Ayendes の返信にいくつかの追加を追加すると思いました (そのうちのいくつかはありましたが、そのような例はありませんでした)従うことができます)、これを理解するのは難しくありませんが、例を使用すると、数時間を費やすのではなく、10 分でこれを解決できたはずです。
私の問題は、アプリケーションにカスタム値型の構造体があることでした。使用する例は EmailAddress です。残念ながら、Ravendb では、カスタム シリアライザーを定義しないと、これらの型に対してクエリを実行できませんでした。
値の型は次のようになります。
[DataContract(Namespace = DataContractNamespaces.ValueTypes)]
public struct EmailAddress : IEquatable<EmailAddress>
{
private const char At = '@';
public EmailAddress(string value) : this()
{
if (value == null)
{
throw new ArgumentNullException("value");
}
this.Value = value;
}
public bool IsWellFormed
{
get
{
return Regex.IsMatch(this.Value, @"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*");
}
}
public string Domain
{
get
{
return this.Value.Split(At)[1];
}
}
[DataMember(Name = "Value")]
private string Value { get; set; }
public static bool operator ==(EmailAddress left, EmailAddress right)
{
return left.Equals(right);
}
public static bool operator !=(EmailAddress left, EmailAddress right)
{
return !left.Equals(right);
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
return this.Equals(new EmailAddress(obj.ToString()));
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public override string ToString()
{
return this.Value;
}
public bool Equals(EmailAddress other)
{
return other != null && this.Value.Equals(other.ToString(), StringComparison.OrdinalIgnoreCase);
}
}
保存してクエリしたいドキュメントのタイプは、次のようになります。
public class Customer
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public EmailAddress Email { get; set; }
}
メールを生の文字列として保存し、取得時に値の型に戻すカスタム シリアライザーは次のようになります。
public class EmailConverterTest : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(EmailAddress);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
EmailAddress actualAddress = new EmailAddress(reader.Value.ToString());
return actualAddress;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
EmailAddress actualAddress = (EmailAddress)value;
string stringEmail = actualAddress.ToString();
writer.WriteValue(stringEmail);
}
}
最後に、私はそれを配線し、次のようにすべてを照会することができました:
public static void serializercustom(Newtonsoft.Json.JsonSerializer serialiser)
{
serialiser.Converters.Add(new EmailConverterTest());
}
public static void TestCustomer()
{
using (var documentStore = new DefaultDocumentStore())
{
documentStore.ConnectionStringName = Properties.Settings.Default.SandBoxConnection;
documentStore.Initialize();
documentStore.Conventions.CustomizeJsonSerializer = new Action<Newtonsoft.Json.JsonSerializer>(serializercustom);
var customer = new Customer
{
Id = Guid.NewGuid(),
FirstName = "TestFirstName",
LastName = "TestLastName",
Email = new EmailAddress("testemail@gmail.com")
};
// Save and retrieve the data
using (var session = documentStore.OpenSession())
{
session.Store(customer);
session.SaveChanges();
}
using (var session = documentStore.OpenSession())
{
var addressToQuery = customer.Email;
var result = session.Query<Customer>(typeof(CustomerEmailIndex).Name).Customize(p => p.WaitForNonStaleResults()).Where(p => p.Email == addressToQuery);
Console.WriteLine("Number of Results {0}", result.Count()); // This always seems to return the matching document
}
}
}